The whole problem with error handling is recognizing that lots of errors can crop up including some that you expect. However, there can be many causes for the error you named. You have gotten several suggestions for this and they are all good. I cannot tell you what to do, but I can tell you how I approached the problem.
Part 1. Every form had an explicit SAVE button that set a flag (see Isaac's post for a similar approach). That SAVE button did the work and if you did something else (like try to navigate or close the form) my BeforeUpdate event code would catch that you were trying to save a "dirty" form in an unauthorized way. It would cancel any save that didn't go through the CLOSE button.
Part 2. Every data-oriented control on every form was either critical or non-critical. In the FormCurrent routine, code would set some flags to FALSE. Every critical control's LostFocus event would examine the value in its control and, if it was a value that COULD be saved, it would set the flag to TRUE.
Part 3. Every bound control called a common routine that would make some tests. For example, there was a master flag that would be set each time via ReadyFlag = Crit1 AND Crit2 AND Crit3 AND.... CRITn that I would use to make the SAVE button visible. Therefore, if all critical values had not been handled yet, you literally had NO controls that would allow you to save the values or close the form. This common routine would test whether the form was "dirty" and if it was, it turned ON the UNDO button and also turned off the form's navigation controls and CLOSE button. Therefore, there would be a time when your only choice was to either UNDO everything or keep on entering data until the SAVE flag would come on. In that state, you could neither close nor save nor navigate. You could only UNDO or continue entering data.
Part 4. The BeforeUpdate event would test whether your record was ready AND whether you used the SAVE button to trigger the record save operation. It worked in concert with...
Part 5. The AfterUpdate event did event logging, adjusted the navigation controls, and diddled with the states of the control buttons.
Yes, this was an extensive bit of work. And it wasn't bullet-proof. But it did a darned good job in taking away a person's opportunity to make a bad mistake by leaving you with bad data.
This is relevant to error handling in this way: Those precautions made a lot of user-induced data errors impossible because I literally did not allow them to see the functions that would give them the chance to screw up. So my approach was to prevent the errors ahead of time.
The other issue is that if you have an error anyway, you have to try to write your code so that after any questionable action, try to check the error flag and if you had an error, you need to drop the users back to a state where they can retry the function just attempted.