Validation and Error Handling
Reject bad input early, and turn every failure into a clean, predictable response.
Big Idea: A server that only handles the happy path is a demo, not a product. Real requests arrive with missing fields, wrong types, and unexpected failures deep inside your code. Validation stops bad input at the door; error handling makes sure that when something does go wrong, the client gets a clear, consistent answer instead of a crash or a leaked stack trace.
By the end of this topic you will be able to:
- validate incoming data at the trust boundary, by hand and with a schema library,
- signal failures with the
Errorobject and a custom error class that carries a status code, - catch asynchronous errors so they reach Express instead of crashing the process,
- write one central error-handling middleware that formats every error the same way,
- choose correct HTTP status codes and a consistent JSON error shape.
1. Two different jobs
People lump these together, but they solve different problems:
- Validation is proactive. Before you touch a database or run business logic, you check that the input is shaped correctly - the right fields, the right types, sensible values. Bad input is rejected immediately with a
400 Bad Request. - Error handling is reactive. Even with perfect input, things fail: the database is down, a file is missing, a third-party API times out. Error handling decides what the client sees when that happens.
Analogy. Validation is the bouncer at the door checking IDs - wrong ID, you do not get in. Error handling is the first-aid kit inside: no matter what goes wrong once you are in, there is a calm, standard procedure instead of panic. You want both.
The golden rule that ties them together: never trust input, and never let an unhandled error reach the user as a raw crash.