Skillshub Common Error Handling
Cross-cutting standards for error design, response shapes, error codes, and boundary placement. Use when handling errors, designing exception flows, or standardizing error responses.
install
source · Clone the upstream repo
git clone https://github.com/ComeOnOliver/skillshub
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/ComeOnOliver/skillshub "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/HoangNguyen0403/agent-skills-standard/error-handling" ~/.claude/skills/comeonoliver-skillshub-common-error-handling-063e59 && rm -rf "$T"
manifest:
skills/HoangNguyen0403/agent-skills-standard/error-handling/SKILL.mdsource content
Common Error Handling Standards
Priority: P1 (OPERATIONAL)
Consistent, predictable error handling is the backbone of maintainable systems. Errors are first-class citizens — design them explicitly.
🏗 Error Response Shape (HTTP APIs)
All API errors MUST use a consistent envelope:
{ "error": { "code": "USER_NOT_FOUND", "message": "The requested user does not exist.", "traceId": "4bf92f3577b34da6a3ce929d0e0e4736", "details": [] } }
| Field | Rule |
|---|---|
| SCREAMING_SNAKE_CASE machine-readable code. Never localize. |
| Human-readable English summary. Safe for end-users (no stack traces). |
| Correlation ID from the request context. |
| Optional array of field-level validation errors. Empty for non-validation errors. |
🗂 Error Classification
| Layer | Error Type | Strategy |
|---|---|---|
| Validation | | Return with field paths |
| Authentication | | Generic message — never expose reason |
| Authorization | | Log attempt, never expose role info |
| Not Found | | Distinguishable from auth errors |
| Conflict | | Include conflicting resource ID |
| Unhandled | | Log full context, return generic message |
📦 Error Wrapping vs Replacement
- Wrap when adding context:
(Go) /fmt.Errorf("processOrder: %w", err)
(JS).new ServiceError('msg', { cause: err }) - Replace only when the original error leaks sensitive internal details.
- Never swallow: Catch without logging or re-throwing hides bugs — forbidden.
🛡 Boundary Placement
- API Layer: Translate domain/infrastructure errors into HTTP responses. Use a global exception filter/middleware.
- Domain Layer: Throw domain-specific errors (e.g.,
). Never reference HTTP status codes.InsufficientStockError - Infrastructure Layer: Throw infrastructure errors (e.g.,
). Wrap 3rd party exceptions.DatabaseConnectionError - Never: Let infrastructure errors (raw DB/network exceptions) bubble up to the API response.
Request → [API Layer: maps to HTTP] → [Domain: business errors] → [Infra: DB/network errors]
🔢 Error Code Design
- Codes are permanent IDs — treat them like API contracts. Once published, never rename.
- Format:
→<DOMAIN>_<NOUN>_<VERB>
,ORDER_PAYMENT_FAILED
.USER_EMAIL_DUPLICATE - Define in a centralized constants file; never inline magic strings.
Anti-Patterns
- No
: Always log or re-throw.catch(e) {} - No stack traces in responses: Leak internal structure to attackers.
- No generic
for validation: Use500
with400
.details - No HTTP status codes in domain layer: Domain errors are business concepts, not transport decisions.
- No error-code proliferation: Prefer a small, well-documented set over one code per exception class.