All tools
SkillCurated · reviewed
Error-Handling Audit Skill
Updated Jul 7, 2026
A Claude Code skill that scans code for inadequate error handling: swallowed exceptions, empty catch blocks, silent fallbacks that hide failures, and catch-all handlers that lose error type and context. Each finding proposes a concrete, targeted fix.
What it does
- /audit-errors
Scan code for swallowed errors, empty catch blocks, silent fallbacks, and catch-all handlers.
- /audit-errors <file>
Audit a specific file or function for error-handling problems and propose targeted fixes.
Files (1)
SKILL.mdprimary · markdown · 4.3 KB
# Error-Handling Audit Skill
---
slug: error-handling-audit-skill
version: 1.0.0
category: engineering
command: /audit-errors
---
## What it does
Scans a function, file, or module for inadequate error handling and proposes fixes.
Targets the most dangerous patterns: empty catch blocks, swallowed rejections,
silent fallbacks that return null/undefined on failure, and generic catch-all handlers
that erase the error type and its context.
## Trigger
Use this skill when asked to audit, review, or improve error handling.
Typical invocations:
- "Audit this file for swallowed errors"
- "Why is this function silently failing?"
- `/audit-errors` in Claude Code
- `/audit-errors <file>` to target a specific file or function
## Input
Provide one or more of:
1. The code to audit (pasted or referenced by file path)
2. The language and runtime (TypeScript/Node, Python, Go, etc.)
3. The error-handling conventions in use (custom error classes, Result types, structured logging)
4. Known failure modes you want to check specifically
## Method
Scan for these patterns, in descending severity:
### Critical
- **Empty catch block** — `catch (e) {}` or `except: pass` — error is swallowed completely.
- **Unhandled promise rejection** — `someAsync()` called without `await` or `.catch()`, or a
`Promise.all` where one rejection silently voids the rest.
- **Ignored return value carrying an error** — Go-style `val, _ := fn()` where `_` discards an error.
### High
- **Silent null/undefined fallback** — `catch (e) { return null; }` where the caller cannot
distinguish "not found" from "error".
- **Catch-all that loses type** — `catch (e: unknown) { console.log(e); }` without re-throw,
error class check, or structured logging.
- **async function that never rejects or resolves** — dangling promise from a missing `return`.
### Medium
- **Error logged but not surfaced** — the error is logged but the function returns a success
value, misleading the caller.
- **Stack trace discarded** — `throw new Error(e.message)` re-wraps without `{ cause: e }`,
losing the original stack.
- **Overly broad catch** — catches `Error` when only `NetworkError` is expected; hides programming errors.
### Low
- **Inconsistent error shape** — some paths throw, others return `{ error: string }`; callers must handle both.
- **Missing finally** — resource (file handle, DB connection, lock) not released on error path.
## Output format
Produce a findings list sorted by severity, then a **Summary** table.
For each finding, show the problematic code snippet and the proposed fix side by side.
```
## Findings
[Critical] Empty catch block swallows all errors from fetchUser()
File: src/api/user.ts, line 24
Before: catch (e) {}
After: catch (e) { logger.error('fetchUser failed', { userId, error: e }); throw e; }
## Summary
| Severity | Count |
|----------|-------|
| Critical | N |
| High | N |
| Medium | N |
| Low | N |
```
## Example output
```
## Findings
[Critical] Unhandled promise rejection in background sync (src/sync.ts:41)
Before: sync().catch(() => {})
After: sync().catch((e) => logger.error('Background sync failed', { error: e }));
Why: Silently ignoring a sync failure means data loss goes undetected.
[High] fetchConfig returns null on error, caller cannot distinguish missing vs. broken (src/config.ts:18)
Before: catch (e) { return null; }
After: catch (e) { throw new ConfigFetchError('Failed to load remote config', { cause: e }); }
Why: The caller does null checks that will silently use stale config when the fetch errors.
[Medium] Error re-thrown without cause, original stack is lost (src/db.ts:55)
Before: throw new Error(e.message)
After: throw new DatabaseError('Query failed', { cause: e })
Why: Node's native error chaining (cause) preserves the original stack in logs and monitoring tools.
[Low] DB connection not closed in error path — missing finally (src/db.ts:72)
Fix: Wrap the query block in try/finally and call conn.release() in the finally block.
## Summary
| Severity | Count |
|----------|-------|
| Critical | 1 |
| High | 1 |
| Medium | 1 |
| Low | 1 |
```
## Commands (Claude Code)
- `/audit-errors` — Scan the selected or pasted code for error-handling problems and propose fixes.
- `/audit-errors <file>` — Audit a specific file or function by name or pasted content.