Agent skill

Error Handling

by kid-sid in kid-sid/claude-spellbook

A skill your agent uses when designing error hierarchies, propagating errors across service boundaries, implementing retry and backoff logic, writing structured error responses for APIs, or making…

MITAuto-check passedBackend & APIs

Install Error Handling

skills CLI
$ npx skills add kid-sid/claude-spellbook --skill error-handling -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install kid-sid/claude-spellbook error-handling --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/kid-sid/claude-spellbook.git skills-src && mkdir -p .claude/skills && cp -r skills-src/skills/error-handling .claude/skills/error-handling && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
error-handling
GitHub stars
189
Token cost
~3k tokens
SKILL.md length
541 words
Files
1
Skills in repo
54
Repo updated
First seen
Licence
MIT

At a glance

A skill your agent uses when designing error hierarchies, propagating errors across service boundaries, implementing retry and backoff logic, writing structured error responses for APIs, or making…

  • Designing error hierarchies
  • SKILL.md covers When to Activate, Error Classification, Custom Error Hierarchies and Adding Context Without Losing…, plus 5 more sections
  • Instructions only: no scripts, shell commands, URLs or credentials in SKILL.md
  • Propagating errors across service boundaries

What it does

Error Handling is an agent skill from kid-sid/claude-spellbook. Use when designing error hierarchies, propagating errors across service boundaries, implementing retry and backoff logic, writing structured error responses for APIs, or making error handling consistent across a Python, TypeScript, or Go codebase.

Its SKILL.md is about 3k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.

It sits in Backend & APIs, covering Error handling and Microservices. It works with Python and TypeScript. The repository describes itself as: A curated collection of skills, prompts, and workflows that extend Claude's capabilities — your personal grimoire for AI-powered development. The licence is MIT.

When your agent uses it

  • Designing error hierarchies
  • Propagating errors across service boundaries
  • Implementing retry and backoff logic
  • Writing structured error responses for APIs

Example prompts

  • “/error-handling”

Requirements

  • Python 3

What it can do on your machine

Read from SKILL.md and the folder at commit a7c2ac9. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    No scripts in the folder and no shell commands in SKILL.md (its code samples are python, typescript, go and json).

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    No URLs in SKILL.md.

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Error Handling loads about 3k tokens when it runs. Until then it costs about 66 tokens; SKILL.md has 541 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~66
When it runs · the whole SKILL.md, loaded when a task matches
~3k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from kid-sid/claude-spellbook at commit a7c2ac9, republished under its MIT licence (© kid-sid). 541 words, ~2,969 tokens.

Download SKILL.mdSave it as .claude/skills/error-handling/SKILL.md (or your agent's skills folder).
name
error-handling
description
Use when designing error hierarchies, propagating errors across service boundaries, implementing retry and backoff logic, writing structured error responses for APIs, or making error handling consistent across a Python, TypeScript, or Go codebase.

Error Handling

Patterns for structured errors, propagation, retries, and consistent failure surfaces across Python, TypeScript, and Go.

When to Activate

  • Designing a custom exception or error hierarchy for a service
  • Propagating errors across HTTP, gRPC, or queue boundaries
  • Implementing retry logic with exponential backoff and jitter
  • Writing consistent error responses for a REST or GraphQL API
  • Distinguishing recoverable from unrecoverable errors
  • Auditing a codebase for swallowed exceptions or bare except blocks
  • Adding context to errors without losing the original cause

Error Classification

Classify errors before deciding how to handle them — the right response depends on what kind of failure occurred.

ClassExamplesHandle by
ValidationMissing field, bad formatReturn 400 immediately — no retry
Not foundUnknown ID, deleted resourceReturn 404 — no retry
AuthInvalid token, expired sessionReturn 401/403 — no retry
TransientNetwork timeout, DB connection blipRetry with backoff
DependencyThird-party API down, queue unavailableRetry, then circuit-break
Logic bugNull deref, assertion failureLog + alert — do not retry or swallow
Rate limited429 from upstreamRetry after Retry-After header

Custom Error Hierarchies

Python
python
# Base domain error — all app errors inherit from this
class AppError(Exception):
    def __init__(self, message: str, code: str, status: int = 500) -> None:
        super().__init__(message)
        self.code = code
        self.status = status

class NotFoundError(AppError):
    def __init__(self, resource: str, id: str) -> None:
        super().__init__(f"{resource} '{id}' not found", "NOT_FOUND", 404)

class ValidationError(AppError):
    def __init__(self, field: str, reason: str) -> None:
        super().__init__(f"Invalid '{field}': {reason}", "VALIDATION_ERROR", 400)

class TransientError(AppError):
    """Signals a retry is safe."""
    def __init__(self, message: str) -> None:
        super().__init__(message, "TRANSIENT_ERROR", 503)
TypeScript
typescript
// Tagged union — exhaustive handling without instanceof chains
type AppError =
  | { tag: "NOT_FOUND"; resource: string; id: string }
  | { tag: "VALIDATION"; field: string; reason: string }
  | { tag: "UNAUTHORIZED" }
  | { tag: "TRANSIENT"; message: string; retryable: true };

function notFound(resource: string, id: string): AppError {
  return { tag: "NOT_FOUND", resource, id };
}

// Result type — explicit error path, no throw/catch in business logic
type Result<T, E = AppError> = { ok: true; value: T } | { ok: false; error: E };

function ok<T>(value: T): Result<T> { return { ok: true, value }; }
function err<E>(error: E): Result<never, E> { return { ok: false, error }; }

// Usage
async function getUser(id: string): Promise<Result<User>> {
  const user = await db.findUser(id);
  if (!user) return err(notFound("User", id));
  return ok(user);
}

const result = await getUser("123");
if (!result.ok) {
  // result.error is fully typed here
  switch (result.error.tag) {
    case "NOT_FOUND": return res.status(404).json({ error: result.error });
    case "UNAUTHORIZED": return res.status(401).json({ error: "Unauthorized" });
  }
}
Go
go
// Sentinel errors for classification
var (
    ErrNotFound   = errors.New("not found")
    ErrValidation = errors.New("validation error")
    ErrTransient  = errors.New("transient error")
)

// Structured error with context
type AppError struct {
    Code    string
    Message string
    Err     error  // wrapped cause
}

func (e *AppError) Error() string { return e.Message }
func (e *AppError) Unwrap() error { return e.Err }

func NotFound(resource, id string) *AppError {
    return &AppError{
        Code:    "NOT_FOUND",
        Message: fmt.Sprintf("%s '%s' not found", resource, id),
        Err:     ErrNotFound,
    }
}

// Propagate with context — never discard the original error
func getUser(ctx context.Context, id string) (*User, error) {
    user, err := db.FindUser(ctx, id)
    if err != nil {
        if errors.Is(err, sql.ErrNoRows) {
            return nil, NotFound("User", id)
        }
        return nil, fmt.Errorf("getUser %s: %w", id, err)
    }
    return user, nil
}

// Check error class at the boundary
if errors.Is(err, ErrNotFound) {
    http.Error(w, "Not found", http.StatusNotFound)
    return
}
if errors.Is(err, ErrTransient) {
    http.Error(w, "Service unavailable", http.StatusServiceUnavailable)
    return
}

Adding Context Without Losing the Cause

python
# Python — chain exceptions
try:
    result = db.query(sql)
except psycopg2.OperationalError as exc:
    raise TransientError("database unavailable") from exc  # preserves __cause__

# BAD — swallows the original traceback
raise TransientError("database unavailable")
typescript
// TypeScript — wrap with cause
throw new Error("Database unavailable", { cause: originalError });

// BAD — loses original stack
throw new Error("Database unavailable");
go
// Go — %w verb wraps for errors.Is / errors.As
return fmt.Errorf("fetchOrders: %w", err)   // ✓ preserves chain

// BAD — breaks unwrapping
return fmt.Errorf("fetchOrders: %v", err)   // ✗ wraps as string only
return errors.New("fetchOrders failed")     // ✗ discards original

Retry with Exponential Backoff and Jitter

Jitter prevents thundering herd when many callers retry simultaneously.

python
# Python
import asyncio, random

async def with_retry(fn, *, max_attempts: int = 3, base_delay: float = 0.5):
    for attempt in range(max_attempts):
        try:
            return await fn()
        except TransientError:
            if attempt == max_attempts - 1:
                raise
            delay = base_delay * (2 ** attempt) + random.uniform(0, 0.3)
            await asyncio.sleep(delay)
typescript
// TypeScript
async function withRetry<T>(
  fn: () => Promise<T>,
  { maxAttempts = 3, baseDelay = 500 } = {}
): Promise<T> {
  for (let attempt = 0; attempt < maxAttempts; attempt++) {
    try {
      return await fn();
    } catch (err) {
      if (!isRetryable(err) || attempt === maxAttempts - 1) throw err;
      const delay = baseDelay * 2 ** attempt + Math.random() * 300;
      await new Promise((r) => setTimeout(r, delay));
    }
  }
  throw new Error("unreachable");
}

function isRetryable(err: unknown): boolean {
  return err instanceof AppError && err.tag === "TRANSIENT";
}
go
// Go
func WithRetry(ctx context.Context, fn func() error, maxAttempts int) error {
    var err error
    for attempt := range maxAttempts {
        if err = fn(); err == nil {
            return nil
        }
        if !errors.Is(err, ErrTransient) {
            return err
        }
        if attempt == maxAttempts-1 {
            break
        }
        delay := time.Duration(math.Pow(2, float64(attempt))*500)*time.Millisecond +
            time.Duration(rand.Intn(300))*time.Millisecond
        select {
        case <-time.After(delay):
        case <-ctx.Done():
            return ctx.Err()
        }
    }
    return fmt.Errorf("after %d attempts: %w", maxAttempts, err)
}

Structured API Error Responses

Every API error should include: machine-readable code, human-readable message, optional details for field-level problems.

json
{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Request validation failed",
    "details": [
      { "field": "email", "reason": "must be a valid email address" },
      { "field": "age",   "reason": "must be a positive integer" }
    ],
    "request_id": "req_01HX..."
  }
}
python
# FastAPI global handler
from fastapi import Request
from fastapi.responses import JSONResponse

@app.exception_handler(AppError)
async def app_error_handler(request: Request, exc: AppError) -> JSONResponse:
    return JSONResponse(
        status_code=exc.status,
        content={
            "error": {
                "code": exc.code,
                "message": str(exc),
                "request_id": request.state.request_id,
            }
        },
    )
typescript
// Express global error handler — must be last middleware
app.use((err: unknown, req: Request, res: Response, _next: NextFunction) => {
  const requestId = req.headers["x-request-id"] ?? crypto.randomUUID();
  if (err instanceof AppError) {
    return res.status(err.status).json({
      error: { code: err.code, message: err.message, request_id: requestId },
    });
  }
  console.error("Unhandled error", err);
  res.status(500).json({
    error: { code: "INTERNAL_ERROR", message: "An unexpected error occurred", request_id: requestId },
  });
});

Logging Errors

SeverityWhenFields to include
ERRORUnhandled or unexpected failuresmessage, stack, request_id, user_id
WARNHandled but notable (retry succeeded, degraded mode)message, attempt count
INFOExpected failures returned to caller (404, 400)code, path — no stack trace
DEBUGRetry attempts, circuit stateattempt, delay, error message
python
# BAD — log and re-raise doubles the noise
except SomeError as exc:
    logger.error("Failed", exc_info=True)
    raise  # logged again by the global handler

# GOOD — log once at the boundary, propagate elsewhere
except SomeError as exc:
    raise TransientError("upstream failed") from exc  # logged once at the top

Show full SKILL.md (274 more words)Show less

Red Flags

  • Bare except / catch (e) {} — swallows the error entirely; always re-raise or handle explicitly.
  • Retrying non-retryable errors — retrying a 400 or 404 wastes time and can amplify load; check error class before retrying.
  • raise Exception("something went wrong") — generic base types give callers no way to branch; use typed domain errors.
  • Logging and re-raising at every layer — logs the same error multiple times; propagate up and log once at the boundary.
  • Using %v instead of %w in Go — breaks errors.Is / errors.As unwrapping; always use %w when wrapping.
  • Ignoring err in Go — _ = fn() silently discards failures; use //nolint:errcheck only with a documented reason.
  • No request_id in error responses — makes support and debugging impossible; always include a correlation ID.
  • Returning 500 for client errors — masks bugs; map domain errors to the correct 4xx before they reach the handler.
  • Retry without jitter — synchronized retries hammer a recovering dependency; always add random jitter.

Checklist

  • Custom error types carry code, message, and HTTP status — no raw Exception("string") at boundaries
  • Errors are wrapped with context at each layer (from exc / { cause } / %w) — original cause preserved
  • Error class determined before retrying — only TRANSIENT errors retried, never validation or auth errors
  • Retry uses exponential backoff with jitter — no fixed-interval loops
  • Global error handler present — no unhandled errors reaching the framework default
  • API error responses include code, message, and request_id — consistent shape across all endpoints
  • Errors logged once at the top boundary — not re-logged at every layer
  • INFO used for expected 4xx, ERROR for unexpected 5xx — no stack traces in 404 logs
  • Go functions never ignore error return values without a documented reason
  • Circuit breaker or fallback present for calls to external dependencies

© kid-sid, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

Just SKILL.md in skills/error-handling of kid-sid/claude-spellbook.

Open the folder on GitHubat commit a7c2ac9

Compare with similar skills

Error Handling next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Error Handling compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Error Handling this skillkid-sid/claude-spellbook189—~3kAutomated safety check: PassMIT
AWS Lambda Durable Functionsawslabs/agent-plugins912—~2.3kAutomated safety check: PassApache-2.0
Nodejsblencorp/claude-code-kit106—~2.6kAutomated safety check: PassMIT
Node Backend Development Guidelinesdiet103/claude-code-infrastructure-showcase10k2 repos~2kAutomated safety check: PassMIT
AWS Serverless Edazxkane/aws-skills3674 repos~3.2kAutomated safety check: PassMIT
Temporal Developerlatitude-dev/latitude-llm4.7k—~1.5kAutomated safety check: PassMIT

Similar skills

  • AWS Lambda Durable Functions

    awslabs/agent-plugins

    Official

    Build resilient, long-running, multi-step applications with AWS Lambda durable functions with automatic state persistence, retry logic, and orchestration for long-running executions.

    912 GitHub stars~2.3k tokensUpdated 2 days ago
    Backend & APIsAuto-check passed
  • Nodejs

    blencorp/claude-code-kit

    Core Node.js backend patterns for TypeScript applications including async/await error handling, middleware concepts, configuration management, testing strategies, and layered architecture principles.

    106 GitHub stars~2.6k tokensUpdated 10 mo ago
    Backend & APIsAuto-check passed
  • Node Backend Development Guidelines

    diet103/claude-code-infrastructure-showcase

    Sets layered architecture and coding rules for Node.js, Express and TypeScript microservices, covering routes, controllers, services, repositories, Prisma, Sentry and Zod.

    10k GitHub starsUsed in 2 repos~2k tokens
    Backend & APIsAuto-check passed
  • AWS Serverless Eda

    zxkane/aws-skills

    AWS serverless and event-driven architecture expert based on Well-Architected Framework.

    367 GitHub starsUsed in 4 repos~3.2k tokens
    Backend & APIsAuto-check passed
  • Temporal Developer

    latitude-dev/latitude-llm

    This skill should be used when the user asks to "create a Temporal workflow", "write a Temporal activity", "debug stuck workflow", "fix non-determinism error", "Temporal Python", "Temporal…

    4.7k GitHub stars~1.5k tokensUpdated yesterday
    Backend & APIsAuto-check passed
  • K8e Sandbox

    xiaods/k8e

    Run a goal end to end inside an isolated K8E sandbox pod (gVisor / Kata / Firecracker) instead of on the host: exec bash / Python / Node / TypeScript, install packages, move files in and out, reuse…

    499 GitHub stars~6k tokensUpdated 9 days ago
    Backend & APIsAuto-check passed

More from kid-sid/claude-spellbook

All 54 skills in this repo
  • Accessibility

    kid-sid/claude-spellbook

    A skill your agent uses when building or reviewing UI components for keyboard and screen reader compatibility, adding ARIA to custom widgets, auditing a page for WCAG AA conformance, or preparing…

    189 GitHub stars~3.2k tokensUpdated 2 mo ago
    Auto-check passed
  • Agentex

    kid-sid/claude-spellbook

    A skill your agent uses when building, wiring, or debugging an Agentex agent — choosing agent type, configuring acp.py and manifest.yaml, using adk.messages or adk.state, or resolving…

    189 GitHub stars~2.2k tokensUpdated 2 mo ago
    Auto-check: notes
  • AI Engineer

    kid-sid/claude-spellbook

    A skill your agent uses when building production LLM applications — designing RAG pipelines, choosing vector databases, implementing agent orchestration, optimizing cost, or adding AI safety…

    189 GitHub stars~3.7k tokensUpdated 2 mo ago
    Auto-check passed
  • Angular

    kid-sid/claude-spellbook

    A skill your agent uses when building or refactoring Angular applications — choosing between signals, RxJS, and NgRx for state, configuring routing with guards and lazy loading, optimizing change…

    189 GitHub stars~5k tokensUpdated 2 mo ago
    Auto-check passed
  • API Design

    kid-sid/claude-spellbook

    A skill your agent uses when designing new REST endpoints, reviewing an existing API contract, adding pagination or filtering, planning a versioning strategy, or building a public or partner-facing…

    189 GitHub stars~3.6k tokensUpdated 2 mo ago
    Auto-check passed
  • Auth

    kid-sid/claude-spellbook

    A skill your agent uses when implementing login flows, issuing or validating JWTs, setting up OAuth2/OIDC with a provider, designing role-based or attribute-based access control, securing API…

    189 GitHub stars~3.2k tokensUpdated 2 mo ago
    Auto-check passed

Questions about Error Handling

What does Error Handling do?

A skill your agent uses when designing error hierarchies, propagating errors across service boundaries, implementing retry and backoff logic, writing structured error responses for APIs, or making…. Error Handling is an agent skill from kid-sid/claude-spellbook. Use when designing error hierarchies, propagating errors across service boundaries, implementing retry and backoff logic, writing structured error responses for APIs, or making error handling consistent across a Python, TypeScript, or Go codebase.

When should I use Error Handling?

Error Handling fits situations like: designing error hierarchies; propagating errors across service boundaries; implementing retry and backoff logic; writing structured error responses for APIs.

How do I install Error Handling in Claude Code?

Run `npx skills add kid-sid/claude-spellbook --skill error-handling -a claude-code`. Or copy the skill folder (skills/error-handling in kid-sid/claude-spellbook) into .claude/skills/error-handling in your project. Claude Code loads it when a task matches its description.

How do I install Error Handling in Codex?

Run `npx skills add kid-sid/claude-spellbook --skill error-handling -a codex`. Or copy the skill folder (skills/error-handling in kid-sid/claude-spellbook) into .agents/skills/error-handling in your project. Codex loads it when a task matches its description.

Can I use Error Handling in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add kid-sid/claude-spellbook --skill error-handling -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/error-handling, .gemini/skills/error-handling, .github/skills/error-handling and .opencode/skills/error-handling in your project.

What does Error Handling need to run?

SKILL.md names no scripts, command-line tools or credentials: Error Handling is instructions for the agent only. Our summary lists: Python 3.

Does Error Handling access the network?

SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.

Is Error Handling safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does Error Handling use?

Error Handling is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Error Handling use?

About 3k tokens (SKILL.md is roughly 12k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to Error Handling?

Skills that share tags, products or a category with Error Handling: AWS Lambda Durable Functions (awslabs/agent-plugins, 912 stars), Nodejs (blencorp/claude-code-kit, 106 stars), Node Backend Development Guidelines (diet103/claude-code-infrastructure-showcase, 10k stars) and AWS Serverless Eda (zxkane/aws-skills, 367 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Error Handling?

kid-sid (a GitHub user) maintains it in kid-sid/claude-spellbook, which has 189 GitHub stars. The repository holds 54 skills in this directory. The repository was last updated on August 5, 2026.

Source: kid-sid/claude-spellbook on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.