Agent skill

Error Handling

by affaan-m in affaan-m/ECC

Patterns for robust error handling across TypeScript, Python, and Go.

MITAuto-check passedDevelopment

Install Error Handling

skills CLI
$ npx skills add affaan-m/ECC --skill error-handling -a claude-code

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

GitHub CLI
$ gh skill install affaan-m/ECC 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/affaan-m/ECC.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
276k
Used in
1 other repo
Token cost
~2.7k tokens
SKILL.md length
277 words
Files
1
Skills in repo
683
Repo updated
First seen
Licence
MIT

At a glance

Patterns for robust error handling across TypeScript, Python, and Go.

  • Works in 5 steps: Fail fast and loudly — surface errors at… → Typed errors over string messages —… → User messages ≠ developer messages —… → …
  • Designing error types
  • SKILL.md covers When to Activate, Core Principles, TypeScript / JavaScript and Python, plus 4 more sections
  • Instructions only: no scripts, shell commands, URLs or credentials in SKILL.md

What it does

Error Handling is an agent skill from affaan-m/ECC. Patterns for robust error handling across TypeScript, Python, and Go. Covers typed errors, error boundaries, retries, circuit breakers, and user-facing error messages. Use when designing error types, retries, circuit breakers, or user-facing failure messages in TypeScript, Python, or Go.

Its SKILL.md is about 2.7k 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 Development, covering Error handling. It works with Python and TypeScript. The repository describes itself as: The agent harness performance optimization system. Skills, instincts, memory, security, and research-first development for Claude Code, Codex, Opencode, Cursor and beyond. The licence is MIT.

When your agent uses it

  • Designing error types
  • Circuit breakers
  • User-facing failure messages in TypeScript

Example prompts

  • “Use the error-handling skill to pattern for robust error handling across TypeScript, Python, and Go”
  • “/error-handling”

Requirements

  • Python 3

Workflow steps

5 steps, taken from the first numbered list in SKILL.md.

  1. Fail fast and loudly — surface errors at the boundary where they occur; don't bury them
  2. Typed errors over string messages — errors are first-class values with structure
  3. User messages ≠ developer messages — show friendly text to users, log full context server-side
  4. Never swallow errors silently — every catch block must either handle, re-throw, or log
  5. Errors are part of your API contract — document every error code a client may receive

What it can do on your machine

Read from SKILL.md and the folder at commit 4eb71d9. 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 typescript, python and go).

    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 2.7k tokens when it runs. Until then it costs about 76 tokens; SKILL.md has 277 words of instructions outside code blocks.

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

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 affaan-m/ECC at commit 4eb71d9, republished under its MIT licence (© affaan-m). 277 words, ~2,741 tokens.

Download SKILL.mdSave it as .claude/skills/error-handling/SKILL.md (or your agent's skills folder).
name
error-handling
description
Patterns for robust error handling across TypeScript, Python, and Go. Covers typed errors, error boundaries, retries, circuit breakers, and user-facing error messages. Use when designing error types, retries, circuit breakers, or user-facing failure messages in TypeScript, Python, or Go.
metadata.origin
ECC

Error Handling Patterns

Consistent, robust error handling patterns for production applications.

When to Activate

  • Designing error types or exception hierarchies for a new module or service
  • Adding retry logic or circuit breakers for unreliable external dependencies
  • Reviewing API endpoints for missing error handling
  • Implementing user-facing error messages and feedback
  • Debugging cascading failures or silent error swallowing

Core Principles

  1. Fail fast and loudly — surface errors at the boundary where they occur; don't bury them
  2. Typed errors over string messages — errors are first-class values with structure
  3. User messages ≠ developer messages — show friendly text to users, log full context server-side
  4. Never swallow errors silently — every catch block must either handle, re-throw, or log
  5. Errors are part of your API contract — document every error code a client may receive

TypeScript / JavaScript

Typed Error Classes
typescript
// Define an error hierarchy for your domain
export class AppError extends Error {
  constructor(
    message: string,
    public readonly code: string,
    public readonly statusCode: number = 500,
    public readonly details?: unknown,
  ) {
    super(message)
    this.name = this.constructor.name
    // Maintain correct prototype chain in transpiled ES5 JavaScript.
    // Required for `instanceof` checks (e.g., `error instanceof NotFoundError`)
    // to work correctly when extending the built-in Error class.
    Object.setPrototypeOf(this, new.target.prototype)
  }
}

export class NotFoundError extends AppError {
  constructor(resource: string, id: string) {
    super(`${resource} not found: ${id}`, 'NOT_FOUND', 404)
  }
}

export class ValidationError extends AppError {
  constructor(message: string, details: { field: string; message: string }[]) {
    super(message, 'VALIDATION_ERROR', 422, details)
  }
}

export class UnauthorizedError extends AppError {
  constructor(reason = 'Authentication required') {
    super(reason, 'UNAUTHORIZED', 401)
  }
}

export class RateLimitError extends AppError {
  constructor(public readonly retryAfterMs: number) {
    super('Rate limit exceeded', 'RATE_LIMITED', 429)
  }
}
Result Pattern (no-throw style)

For operations where failure is expected and common (parsing, external calls):

typescript
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 fetchUser(id: string): Promise<Result<User>> {
  try {
    const user = await db.users.findUnique({ where: { id } })
    if (!user) return err(new NotFoundError('User', id))
    return ok(user)
  } catch (e) {
    return err(new AppError('Database error', 'DB_ERROR'))
  }
}

const result = await fetchUser('abc-123')
if (!result.ok) {
  // TypeScript knows result.error here
  logger.error('Failed to fetch user', { error: result.error })
  return
}
// TypeScript knows result.value here
console.log(result.value.email)
API Error Handler (Next.js / Express)
typescript
import { NextRequest, NextResponse } from 'next/server'

function handleApiError(error: unknown): NextResponse {
  // Known application error
  if (error instanceof AppError) {
    return NextResponse.json(
      {
        error: {
          code: error.code,
          message: error.message,
          ...(error.details ? { details: error.details } : {}),
        },
      },
      { status: error.statusCode },
    )
  }

  // Zod validation error
  if (error instanceof z.ZodError) {
    return NextResponse.json(
      {
        error: {
          code: 'VALIDATION_ERROR',
          message: 'Request validation failed',
          details: error.issues.map(i => ({
            field: i.path.join('.'),
            message: i.message,
          })),
        },
      },
      { status: 422 },
    )
  }

  // Unexpected error — log details, return generic message
  console.error('Unexpected error:', error)
  return NextResponse.json(
    { error: { code: 'INTERNAL_ERROR', message: 'An unexpected error occurred' } },
    { status: 500 },
  )
}

export async function POST(req: NextRequest) {
  try {
    // ... handler logic
  } catch (error) {
    return handleApiError(error)
  }
}
React Error Boundary
typescript
import { Component, ErrorInfo, ReactNode } from 'react'

interface Props {
  fallback: ReactNode
  onError?: (error: Error, info: ErrorInfo) => void
  children: ReactNode
}

interface State {
  hasError: boolean
  error: Error | null
}

export class ErrorBoundary extends Component<Props, State> {
  state: State = { hasError: false, error: null }

  static getDerivedStateFromError(error: Error): State {
    return { hasError: true, error }
  }

  componentDidCatch(error: Error, info: ErrorInfo) {
    this.props.onError?.(error, info)
    console.error('Unhandled React error:', error, info)
  }

  render() {
    if (this.state.hasError) return this.props.fallback
    return this.props.children
  }
}

// Usage
<ErrorBoundary fallback={<p>Something went wrong. Please refresh.</p>}>
  <MyComponent />
</ErrorBoundary>

Python

Custom Exception Hierarchy
python
class AppError(Exception):
    """Base application error."""
    def __init__(self, message: str, code: str, status_code: int = 500):
        super().__init__(message)
        self.code = code
        self.status_code = status_code

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

class ValidationError(AppError):
    def __init__(self, message: str, details: list[dict] | None = None):
        super().__init__(message, "VALIDATION_ERROR", 422)
        self.details = details or []
FastAPI Global Exception Handler
python
from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse

app = FastAPI()

@app.exception_handler(AppError)
async def app_error_handler(request: Request, exc: AppError) -> JSONResponse:
    return JSONResponse(
        status_code=exc.status_code,
        content={"error": {"code": exc.code, "message": str(exc)}},
    )

@app.exception_handler(Exception)
async def generic_error_handler(request: Request, exc: Exception) -> JSONResponse:
    # Log full details, return generic message
    logger.exception("Unexpected error", exc_info=exc)
    return JSONResponse(
        status_code=500,
        content={"error": {"code": "INTERNAL_ERROR", "message": "An unexpected error occurred"}},
    )

Go

Sentinel Errors and Error Wrapping
go
package domain

import "errors"

// Sentinel errors for type-checking
var (
    ErrNotFound    = errors.New("not found")
    ErrUnauthorized = errors.New("unauthorized")
    ErrConflict     = errors.New("conflict")
)

// Wrap errors with context — never lose the original
func (r *UserRepository) FindByID(ctx context.Context, id string) (*User, error) {
    user, err := r.db.QueryRow(ctx, "SELECT * FROM users WHERE id = $1", id)
    if errors.Is(err, sql.ErrNoRows) {
        return nil, fmt.Errorf("user %s: %w", id, ErrNotFound)
    }
    if err != nil {
        return nil, fmt.Errorf("querying user %s: %w", id, err)
    }
    return user, nil
}

// At the handler level, unwrap to determine response
func (h *Handler) GetUser(w http.ResponseWriter, r *http.Request) {
    user, err := h.service.GetUser(r.Context(), chi.URLParam(r, "id"))
    if err != nil {
        switch {
        case errors.Is(err, domain.ErrNotFound):
            writeError(w, http.StatusNotFound, "not_found", err.Error())
        case errors.Is(err, domain.ErrUnauthorized):
            writeError(w, http.StatusForbidden, "forbidden", "Access denied")
        default:
            slog.Error("unexpected error", "err", err)
            writeError(w, http.StatusInternalServerError, "internal_error", "An unexpected error occurred")
        }
        return
    }
    writeJSON(w, http.StatusOK, user)
}

Retry with Exponential Backoff

typescript
interface RetryOptions {
  maxAttempts?: number
  baseDelayMs?: number
  maxDelayMs?: number
  retryIf?: (error: unknown) => boolean
}

async function withRetry<T>(
  fn: () => Promise<T>,
  options: RetryOptions = {},
): Promise<T> {
  const {
    maxAttempts = 3,
    baseDelayMs = 500,
    maxDelayMs = 10_000,
    retryIf = () => true,
  } = options

  let lastError: unknown

  for (let attempt = 1; attempt <= maxAttempts; attempt++) {
    try {
      return await fn()
    } catch (error) {
      lastError = error
      if (attempt === maxAttempts || !retryIf(error)) throw error

      const jitter = Math.random() * baseDelayMs
      const delay = Math.min(baseDelayMs * 2 ** (attempt - 1) + jitter, maxDelayMs)
      await new Promise(resolve => setTimeout(resolve, delay))
    }
  }

  throw lastError
}

// Usage: retry transient network errors, not 4xx
const data = await withRetry(() => fetch('/api/data').then(r => r.json()), {
  maxAttempts: 3,
  retryIf: (error) => !(error instanceof AppError && error.statusCode < 500),
})

User-Facing Error Messages

Map error codes to human-readable messages. Keep technical details out of user-visible text.

typescript
const USER_ERROR_MESSAGES: Record<string, string> = {
  NOT_FOUND: 'The requested item could not be found.',
  UNAUTHORIZED: 'Please sign in to continue.',
  FORBIDDEN: "You don't have permission to do that.",
  VALIDATION_ERROR: 'Please check your input and try again.',
  RATE_LIMITED: 'Too many requests. Please wait a moment and try again.',
  INTERNAL_ERROR: 'Something went wrong on our end. Please try again later.',
}

export function getUserMessage(code: string): string {
  return USER_ERROR_MESSAGES[code] ?? USER_ERROR_MESSAGES.INTERNAL_ERROR
}

Error Handling Checklist

Before merging any code that touches error handling:

  • Every catch block handles, re-throws, or logs — no silent swallowing
  • API errors follow the standard envelope { error: { code, message } }
  • User-facing messages contain no stack traces or internal details
  • Full error context is logged server-side
  • Custom error classes extend a base AppError with a code field
  • Async functions surface errors to callers — no fire-and-forget without fallback
  • Retry logic only retries retriable errors (not 4xx client errors)
  • React components are wrapped in ErrorBoundary for rendering errors

© affaan-m, 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 affaan-m/ECC.

Open the folder on GitHubat commit 4eb71d9

Used in 1 other repository

We found 2 copies of this SKILL.md (exact, near-identical or edited) in other folders, from 1 other GitHub owner. This page covers the copy in affaan-m/ECC, which our catalogue first saw on October 7, 2026.

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 skillaffaan-m/ECC276k1 repos~2.7kAutomated safety check: PassMIT
Cross-Language Coding Standardszereight/gitlab-mcp2k1 repos~1.4kAutomated safety check: PassMIT
Strict Programming Practicescode-yeongyu/oh-my-openagent70k—~9.5kAutomated safety check: PassCustom licence
Clade SDK Patternsjeremylongshore/tons-of-skills-marketplace2.8k—~1.6kAutomated safety check: PassMIT
Sentry Error Capturejeremylongshore/tons-of-skills-marketplace2.8k—~3kAutomated safety check: PassMIT
Error Handling Patternscuriositech/some_claude_skills244—~3.1kAutomated safety check: PassMIT

Similar skills

  • Shared reference for naming, function size, complexity and error handling rules that reviewer agents apply across TypeScript, Python, Go, Rust, Java, C# and Swift.

    2k GitHub starsUsed in 1 repo~1.4k tokens
    DevelopmentAuto-check passed
  • Strict Programming Practices

    code-yeongyu/oh-my-openagent

    Applies strict, type-first coding rules for Python, Rust, TypeScript and Go, loading the matching language reference before the agent writes or edits any code.

    70k GitHub stars~9.5k tokensUpdated today
    DevelopmentAuto-check passed
  • Clade SDK Patterns

    jeremylongshore/tons-of-skills-marketplace

    Production-ready Anthropic SDK patterns — client config, retries, timeouts, Use when working with sdk-patterns patterns.

    2.8k GitHub stars~1.6k tokensUpdated today
    DevelopmentAuto-check passed
  • Sentry Error Capture

    jeremylongshore/tons-of-skills-marketplace

    Implement advanced error capture and context enrichment with Sentry.

    2.8k GitHub stars~3k tokensUpdated today
    DevelopmentAuto-check passed
  • Error Handling Patterns

    curiositech/some_claude_skills

    Design error handling strategies for TypeScript and Python applications — exception hierarchies, Result/Either types, retry patterns, error boundaries, and structured error logging.

    244 GitHub stars~3.1k tokensUpdated 1 mo ago
    DevelopmentAuto-check passed
  • Error Handling

    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…

    190 GitHub stars~3k tokensUpdated 2 mo ago
    Backend & APIsAuto-check passed

More from affaan-m/ECC

All 683 skills in this repo
  • Skill Stocktake

    affaan-m/ECC

    Audits your installed Claude skills and commands for quality, with a quick mode for recently changed skills and a full mode that evaluates all of them through subagents.

    276k GitHub starsUsed in 5 repos~3.1k tokens
    Auto-check passed
  • Ingests, indexes, searches, edits and monitors video, audio and live streams through the VideoDB Python SDK, returning stream links, clips and timestamps.

    276k GitHub starsUsed in 3 repos~3.5k tokens
    Auto-check: notes
  • Docs Governance

    affaan-m/ECC

    Route broad documentation-governance requests to existing ECC skills and run an opt-in, read-only audit of mapped documentation roles, links, ADR indexes, and evidence references.

    276k GitHub stars~1.1k tokensUpdated today
    Auto-check passed
  • Rules Distillation

    affaan-m/ECC

    Scans installed skills for principles that recur across them and proposes rule-file changes: append, revise, add a section, create a file or leave as covered.

    276k GitHub starsUsed in 2 repos~2.3k tokens
    Auto-check passed
  • Builds DRAFT counterparty agreements from one markdown template and a small JSON spec per party, with clauses picked by the party's role.

    276k GitHub stars~2.9k tokensUpdated today
    Auto-check passed
  • Measures whether agents actually follow a skill, rule or agent definition by generating scenarios at three strictness levels and scoring tool-call traces.

    276k GitHub starsUsed in 1 repo~623 tokens
    Auto-check passed

Categories

Questions about Error Handling

What does Error Handling do?

Patterns for robust error handling across TypeScript, Python, and Go. Error Handling is an agent skill from affaan-m/ECC. Patterns for robust error handling across TypeScript, Python, and Go.

When should I use Error Handling?

Error Handling fits situations like: designing error types; circuit breakers; user-facing failure messages in TypeScript.

How do I install Error Handling in Claude Code?

Run `npx skills add affaan-m/ECC --skill error-handling -a claude-code`. Or copy the skill folder (skills/error-handling in affaan-m/ECC) 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 affaan-m/ECC --skill error-handling -a codex`. Or copy the skill folder (skills/error-handling in affaan-m/ECC) 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 affaan-m/ECC --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 2.7k tokens (SKILL.md is roughly 11k 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: Cross-Language Coding Standards (zereight/gitlab-mcp, 2k stars), Strict Programming Practices (code-yeongyu/oh-my-openagent, 70k stars), Clade SDK Patterns (jeremylongshore/tons-of-skills-marketplace, 2.8k stars) and Sentry Error Capture (jeremylongshore/tons-of-skills-marketplace, 2.8k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Error Handling?

affaan-m (a GitHub user) maintains it in affaan-m/ECC, which has 276,111 GitHub stars. The repository holds 683 skills in this directory. The repository was last updated on October 10, 2026.

Source: affaan-m/ECC on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.