Error handling is the part of a program’s design that deals with failures, treating errors as a normal, first-class part of the system rather than an exceptional afterthought bolted on at the end.1
Styles of handling
Languages represent and propagate errors differently, and each style has trade-offs:
- Exceptions (Java, Python, C#) are thrown and unwind the stack until caught. Convenient, but easy to ignore — an uncaught exception crashes the program, and a signature doesn’t reveal what it might throw.1
- Explicit error returns (Go) return an error value alongside the result; the caller must decide what to do. Verbose, but the error path is impossible to overlook.
- Result / Option types (Rust, many functional languages) make errors part of the return type, and the type system forces the caller to handle both cases.
The modern lean is toward explicit, visible handling. Whatever the style, the universal
anti-pattern is swallowing an error silently — an empty catch {} or an ignored return
turns a recoverable problem into a mysterious one later.
Strategies and good practice
Robust error handling rests on a few habits. Validate at the boundary — distrust input the moment it enters the system, so interior code can assume well-formed values. Choose deliberately between fail fast (stop loudly on programmer bugs and broken invariants) and fail soft / graceful degradation (carry on with reduced functionality on expected, recoverable trouble). Make retry-able operations idempotent so a retry after an ambiguous failure can’t cause duplicate work. These ideas shape how an API or a REST service reports problems to its callers, and they are only trustworthy when proven under bad inputs — which is the job of tests.
Sources
-
Exception handling — Wikipedia, on error and exception handling styles and the trade-offs between them. ↩ ↩2