Well there are design errors during development and hardware errors that can occur at anytime.
Example of design error- passing bad arguments to a function
Example of hardware error- crystal fails to start at low temps due to manufacturing or purchasing failure.
For software development errors, I include code to check all parameters passed to a function. The code is surrounded by conditional macro such as
#if BUILD_TYPE==DEBUG_BUILD
if (PARAMETER_IS_NOT_EXPECTED)
reset(DESIGN_ERROR_1)
#endif
reset halts the program and lets you know where the error was encountered
When the RELEASE BUILD is built, this code is not included, presumably because exhaustive checking has already been performed.
For Hardware Errors, I depend on having a working watchdog timer and a hard error routine. Example:
if (ICS_FAILS_TO_CHANGE_FROM_INTERNAL_OSC_TO_CRYSTAL_OSC)
reset(CRYSTAL_FAIL);
reset can put an error CRYSTAL_FAIL on the LCD, wait a little, and go into an infinite loop so the WDT does a silicon reset. (The controller continues to run on the internal oscillator).