Error messages on the form should help the user and guide them to fill in the fields correctly. More often we see the opposite situation, where an angry form turns red and screams at the user that they are wrong everywhere. This is unpleasant and leads to refusals to fill out the form.
It is not a good idea to check data entry when typing. The user gets an error before he has had a chance to enter everything he needs. It is better to check the data when the form button is pressed. If in your case it makes sense to check the data as the user is typing, you should do it on the blur event, when the cursor moves to another field. It's not perfect, but it's better than the user getting an error when he starts typing the first letters of his email.
It's good when the error message doesn't just point to a problem, but helps to solve it or specifies what went wrong.
Being polite and tactful in reporting mistakes is always a good thing. The user will react more calmly to errors if they are not swearing at them, but politely asking and prompting.
It is bad practice to display error messages in isolation from the fields themselves. I know that this is usually done when developers are a bit lazy. It is technically easier to display all errors in one place without context. But it's better not to do so, it breaks the whole logic of the form and the user may not understand which error refers to which field.
It is best to show the error message below or above the input field. This gives a clear understanding of which field it applies to.
Long and complex forms may need an extra move to give a better understanding of errors. The error field may be hidden at the top of the page and out of sight. By clicking the button on the form, the user won't see which field the error is in. So in this case it's a good solution to show an additional message above the button. At the same time the field itself should also have a message.
Another option is to show the error message as a notification in the upper right corner of the page. This will also help the user understand why he clicks the button of the filled form, and it is not sent.