The error you are getting is a follow-on error because a previous statement failed, the ->prepare() call, but you don't have any error handling to tell you if and why a statement has failed, nor to stop code execution upon an error that will prevent the remainder of the code from running correctly.
You ALWAYS need error handling for statements that can fail. For database statements that can fail - connection, query, prepare, and execute, the simplest way of adding error handling, without adding code at each statement, is to use exceptions for errors and in most cases let php catch and handle the exception, where php will use its error related settings to control what happens with the actual error information (database statement errors will 'automatically' get displayed/logged the same as php errors.) The exception to this rule is when inserting/updating duplicate user data, which is actually something your code needs to address. In this case, your code should catch the exception, detect if a duplicate index error (number) occurred, and setup a message telling the user what was wrong with the data that they submitted. For all other error numbers, just re-throw the exception and let php handle it.
To enable exceptions for errors for the mysqli extension add the following line of code before the point where you make the connection (you can then remove any existing error handling logic since it won't get executed upon an error, simplifying the code) -
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);