handling-errors

SKILL.md

Handling Errors

Iron Laws

  1. Never swallow errors - Empty catch blocks hide bugs that surface later in unrelated places, making them much harder to trace
  2. Never convert errors to booleans - Loses all context and forces callers to guess what went wrong
  3. Preserve error context when wrapping or propagating - upstream handlers need the original cause to make good decisions
  4. Log once where handled, not at every layer - duplicate logs across layers create noise that obscures the real signal

Error Messages

Every error message answers: What happened? Why? How to recover?

For logs (developers):

logger.error("Failed to save user: Connection timeout after 30s", {
  userId: user.id,
  dbHost: config.db.host,
  error: error.stack,
});

For users:

For user-facing error copy, use Skill(ce:writer) with The UX Writer persona. Key principles:

  • Brief and specific (not "Something went wrong")
  • Actionable (tell them what to do next)
  • No blame (never "You entered invalid...")
showError({
  title: "Upload failed",
  message: "File exceeds 10MB limit. Choose a smaller file.",
  actions: [{ label: "Choose file", onClick: selectFile }],
});

Error Categories

Type Examples Handling
Expected Validation, Not found, Unauthorized Return Result type, log info
Transient Network timeout, Rate limit Retry with backoff, log warn
Unexpected Null reference, DB crash Log error, show support ID
Critical Auth down, Payment gateway offline Circuit breaker, alert

Fail Fast vs Degrade Gracefully

Fail fast for critical dependencies:

await connectToDatabase(); // Throws on failure - app can't run without it

Degrade gracefully for optional features:

const prefs = await loadPreferences(userId).catch(() => DEFAULT_PREFS);

Log at the Right Layer

// ❌ Logging at every layer = same error 3x
async function fetchData() {
  try { return await fetch(url); }
  catch (e) { console.error("Fetch failed:", e); throw e; }
}

// ✅ Log once where handled
async function fetchData() {
  const response = await fetch(url);
  if (!response.ok) throw new Error(`HTTP ${response.status}`);
  return response;
}
// Top level logs the error once

Language-Specific Patterns

Anti-Patterns

Pattern Problem Fix
Empty catch blocks Hides errors Log or re-throw
return false on error Loses context Return Result type
Generic "Error" messages Undebuggable Include what/why/context
Logging same error at each layer Log pollution Log once at boundary
Bare except: / catch (e) all Catches system signals Catch specific types
Weekly Installs
8
GitHub Stars
95
First Seen
Feb 12, 2026
Installed on
amp8
antigravity8
github-copilot8
codex8
kimi-cli8
gemini-cli8