Skip to content

/error-handling

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,

From plugin
ecc
303k200 skills71 agents113 commands1 MCP

Claude Code

$ npx -y skills add affaan-m/ECC --skill error-handling --agent claude-code

SKILL.md

error-handling.SKILL.md
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

// 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):

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)

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

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

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:
Read more
@affaan-m
Ships withecc

Your agent can write code, but ECC gives it a coordinated engineering system and toolbox: it plans before it builds, verifies changes with tests, reviews its own work from a fresh context, remembers what matters, and turns repeated wins into reusable skills

303k200 skills71 agents1 MCP
Get the whole plugin, auto-invoked

Stars on GitHub

Momentum

stars in total
302.5k
Star history of affaan-m/ECC on GitHub, a chart by star-history.com

Other skills on ecc.

accessibility
Auto-invoked

accessibility

Design, implement, and audit accessible UI to WCAG 2.2 Level AA across Web, iOS, and Android — semantic ARIA roles and labels,…

@affaan-m@affaan-mInstall Skill
agent-architecture-audit
Auto-invoked

agent-architecture-aud…

Full-stack diagnostic for agent and LLM applications. Audits the 12-layer agent stack for wrapper regression, memory pollution,…

@affaan-m@affaan-mInstall Skill
agent-eval
Auto-invoked

agent-eval

Head-to-head comparison of coding agents (Claude Code, Aider, Codex, etc.) on custom tasks with pass rate, cost, time, and…

@affaan-m@affaan-mInstall Skill
agent-harness-construction
Auto-invoked

agent-harness-construc…

Design and optimize AI agent action spaces, tool definitions, and observation formatting for higher completion rates. Use when…

@affaan-m@affaan-mInstall Skill
agent-introspection-debugging
Auto-invoked

agent-introspection-de…

Structured self-debugging workflow for AI agent failures using capture, diagnosis, contained recovery, and introspection reports.…

@affaan-m@affaan-mInstall Skill
agent-security-hardening
Auto-invoked

agent-security-hardeni…

Security hardening guidance for AI agent frameworks that process untrusted content, invoke tools, write workspace files, manage…

@affaan-m@affaan-mInstall Skill

More skills from other plugins.

brainstorming
Auto-invoked

brainstorming

You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…

@obra@obraInstall Skill
ask-matt

ask-matt

Ask which skill or flow fits your situation. A router over the skills in this repo.

skills13d309k
@mattpocock@mattpocockInstall Skill
compiler-commit

compiler-commit

Use when you want to verify compiler changes and commit with the correct convention. Runs tests, lint, and format, then commits…

react4d252k
@facebook@facebookInstall Skill
act-on-feedback

act-on-feedback

Act on user feedback attached to the current session. Use when the user submits feedback on the session's changes via the Submit…

vscode4d195k
@microsoft@microsoftInstall Skill

Questions about error-handling.

Which coding agents can use error-handling?
error-handling installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.