Error Prevention Checklist: Stop Bugs Before Production
Most production errors come from five families: nulls, boundaries, configuration, concurrency, and error handling. Each has one habit that kills most instances.
The Five Families and Their Habits
| Family | Typical error | Prevention habit |
|---|---|---|
| Null/undefined | Cannot read properties of undefined | Validate at boundaries; fail fast on missing required data |
| Boundaries | IndexError, off-by-one, empty arrays | Test with 0, 1, and max-size inputs — every time |
| Configuration | Works locally, 500 in prod | Fail at startup on missing config, never at first request |
| Concurrency | Race conditions, stale reads | Identify shared mutable state; make critical sections explicit |
| Error paths | Swallowed errors, cascading failures | Every catch must log with context, or rethrow |
Before Writing Code
- Define what "done" looks like for edge cases — empty list, missing field, duplicate submission, zero quantity: decide now, not when the bug arrives.
- Know your failure mode for each integration: if this API times out, do we retry, queue, or fail the request? Undecided = undefined behavior under load.
- Write the one weird test first when the logic is tricky — the test that encodes the edge case.
While Writing Code
- Boundaries get explicit validation. Parse and validate external input once, at the edge (API handler, file reader, message consumer) — then trust it internally. Scattered defensive checks mean nobody knows where the truth is enforced.
- Fail fast with a useful message.
throw new Error('JWT_SECRET is required; set it in .env')at startup beats a mystery 500 on the first login attempt an hour later. - Prefer immutability for shared state. Most concurrency bugs are "two writers to one object"; const-by-default and copy-on-write remove the category.
- Every network call gets a timeout. The default is often no timeout, which turns a slow dependency into your outage.
- No empty catch. If you must swallow, log at minimum a metric — silent failures are the most expensive kind.
Before Committing
- Run the test suite with the new edge-case test included; a red suite is information, not an obstacle.
- Check the diff for leftover debug code, commented-out logic, and TODOs without owners.
- Ask of the diff: "what happens when the input is null / the list is empty / this runs twice?" If any answer is "unclear", that's a bug you just got a free preview of.
Before Deploying
- Config checklist: every env var read by the app exists in the target environment (automate this check — a startup validation block takes ten minutes and pays forever).
- Migrations are backward-compatible: deploy code that works with both old and new schema before dropping anything. Two-phase migrations prevent the classic "deploy broke the old pods" incident.
- Know the rollback: what exactly do you run if this deploy misbehaves, and has anyone run it before? An untested rollback is a plan, not a capability.
- Watch the first five minutes: error rate, latency, and one business metric — deploy verification is a habit, not a formality.
The Test-Case Checklist That Finds Real Bugs
For any function taking a collection, these five inputs catch a disproportionate share of bugs: empty, single element, many elements, all-identical elements, and elements that hit the boundary values (0, negative, max int, very long string). For any time-dependent code: midnight, month-end, leap day, and DST transitions. Teams that add these as table-driven test cases stop re-fixing the same off-by-one every quarter.
Monitoring as Prevention
Some errors cannot be prevented, only detected fast: alert on error-rate changes (not absolute counts — traffic varies), on queue depth growth, and on the business metric that drops when checkout breaks. A five-minute detection window converts an incident into a blip; the same bug unnoticed for a day becomes a postmortem.
The One-Line Summary
Validate at the edges, fail loudly at startup, test boundaries deliberately, and let no error pass silently — those four habits prevent more incidents than any tool you can buy.