error-design
Skill12 starsChanged 4 months agoMITView on GitHub
Reviews error handling and exception design, applying the \"define errors out of existence\" principle. Use when reviewing error handling, when a module throws too many exceptions, or when callers must handle errors they shouldn't need to know about. Not for general caller-burden complexity (use pull-complexity-down); this skill is specifically for exception and error-condition strategy.
In this repository16 other files it gives its agents.
- AGENTS.mdAGENTS.md
- abstraction-qualitySkill
- code-evolutionSkill
- comments-docsSkill
- complexity-recognitionSkill
- deep-modulesSkill
- design-it-twiceSkill
- design-reviewSkill
- diagnoseSkill
- general-vs-specialSkill
- information-hidingSkill
- module-boundariesSkill
- naming-obviousnessSkill
- pull-complexity-downSkill
- red-flagsSkill
- strategic-mindsetSkill
The file
We split this skill into the rules it gives an agent
4 rules. About 0 are common, 4 are distinctive, and 0 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈4
Distinctive · estimate
This author's own choices. Worth a look.
0
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 10
When invoked with $ARGUMENTS, focus the analysis on the specified file or module.
- Distinctive: line 21
When a function has many error cases or throws many exception types
- Distinctive: line 22
When callers are burdened with handling errors that rarely occur
- Distinctive: line 23
When error handling code is longer than the happy path
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Error Design Review Lens
When invoked with $ARGUMENTS, focus the analysis on the specified file or module. Read the target code first, then apply the checks below.
Each exception a module throws is an interface element. The best way to deal with exceptions is to not have them.
The "Too Many Exceptions" Anti-Pattern
Programmers are often taught that "the more errors detected, the better," but this produces an over-defensive style that throws exceptions for anything suspicious. Throwing is easy. Handling is hard. Each exception type in a module's interface is one more thing callers must understand and prepare for, making the class shallower than it needs to be. Exception handlers are rarely exercised in practice, which means bugs in them accumulate silently. When a handler is finally needed, it may not work.
When to Apply
- Reviewing error handling code or exception hierarchies
- When a function has many error cases or throws many exception types
- When callers are burdened with handling errors that rarely occur
- When error handling code is longer than the happy path
Core Principles
The Decision Tree
The four techniques below have no canonical ordering. This tree sequences them by preference for practical use.
For every error condition:
1. Can the error be defined out of existence?
Change the interface so the condition isn't an error. If yes: do this. Always the best option.
2. Can the error be masked?
Handle internally without propagating. If yes: mask if handling is safe and complete.
3. Can the error be aggregated?
Replace many specific exceptions with one general mechanism. If yes: aggregate to reduce interface surface.
4. Must the caller handle it?
Propagate only if the caller genuinely must decide. If the caller can't do anything meaningful: crash.
Define Errors Out of Existence
Error conditions follow from how an operation is specified. Change the specification, and the error disappears.
The general move: instead of "do X" (fails if preconditions aren't met), write "ensure state S" (trivially satisfied if state already holds).
- Unset variable? "Delete this variable" (fails if absent) → "ensure this variable no longer exists" (always succeeds)
- File not found on delete? Unix
unlinkdoesn't "delete a file." It removes a directory entry. Returns success even if processes have the file open. - Substring not found? Python slicing clamps out-of-range indices (no exception, no defensive code). Java's
substringthrowsIndexOutOfBoundsException, forcing bounds-clamping around a one-line call.
Defining errors out of existence is like a spice: a small amount improves the result but too much ruins the dish. The technique only works when the exception information is genuinely not needed outside the module. A networking module that masked all network exceptions left callers with no way to detect lost messages or failed peers. Those errors needed to be exposed because callers depended on them to build reliable applications.
Exception Masking
Handle internally without exposing to callers. Valid when:
- The module can recover completely
- Recovery doesn't lose important information
- The masking behavior is part of the module's specification
TCP masks packet loss this way. Before masking, ask whether a developer debugging the system would want to know it happened. If yes, log it. If the loss is irreversible and important, don't mask. Propagate.
Exception Aggregation
Replace many specific exceptions with fewer general ones handled in one place. Masking absorbs errors low and aggregation catches errors high. Together they produce an hourglass where middle layers have no exception handling at all.
Web Server Pattern
Let all NoSuchParameter exceptions propagate to the top-level dispatcher where a single handler generates the error response. New handlers automatically work with the system. The same applies to any request-processing loop: catch in one place near the top, abort the current request, clean up and continue.
Aggregation Through Promotion
Rather than building separate recovery for each failure type, promote smaller failures into a single crash-recovery mechanism. Fewer code paths, more frequently exercised (which surfaces bugs in recovery sooner). Trade-off: promotion increases recovery cost per incident, so it only makes sense when the promoted errors are rare.
Just Crash
When an error is difficult or impossible to handle and occurs infrequently, the simplest response is to print diagnostic information and abort. Out-of-memory errors fit this pattern because there's not much an application can do and the handler itself may need to allocate memory. The same principle applies anywhere: wrap the operation so it aborts on failure, eliminating exception handling at every call site.
Appropriate When
The error is infrequent, recovery is impractical, and the caller can't do anything meaningful.
Not Appropriate When
The system's value depends on handling that failure (e.g., a replicated storage system must handle I/O errors, not crash on them).
Review Process
- Inventory exceptions: List every error case, exception throw, and error return.
- Apply the decision tree: Can each one be defined out? Masked? Aggregated?
- Check depth impact: How many exception types are in the module's interface?
- Audit catch blocks: Are callers doing meaningful work, or just logging and re-throwing?
- Evaluate safety: For any proposed masking, verify nothing important is lost.
- Recommend simplification: Propose specific reductions in error surface.
Red flag signals for error design are cataloged in red-flags (Catch-and-Ignore, Overexposure, Shallow Module).
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

