Agent skill

Error Handling

by CloudAI-X in CloudAI-X/claude-workflow-v2

Implements error handling patterns, structured logging, retry strategies, circuit breakers, and graceful degradation.

MITAuto-check passedDevelopment

Install Error Handling

skills CLI
$ npx skills add CloudAI-X/claude-workflow-v2 --skill error-handling -a claude-code

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

GitHub CLI
$ gh skill install CloudAI-X/claude-workflow-v2 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/CloudAI-X/claude-workflow-v2.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
1.4k
Token cost
~3.4k tokens
SKILL.md length
88 words
Files
1
Skills in repo
13
Repo updated
First seen
Licence
MIT

At a glance

Implements error handling patterns, structured logging, retry strategies, circuit breakers, and graceful degradation.

  • Designing error handling
  • SKILL.md covers Error Handling Workflow, Error Handling Patterns by…, Structured Logging and Error Boundaries and Graceful…, plus 4 more sections
  • Instructions only: no scripts, shell commands, URLs or credentials in SKILL.md
  • Setting up logging

What it does

Error Handling is an agent skill from CloudAI-X/claude-workflow-v2. Implements error handling patterns, structured logging, retry strategies, circuit breakers, and graceful degradation. Use when designing error handling, setting up logging, implementing retries, adding error tracking, or when asked about error boundaries, log aggregation, alerting, or resilience patterns.

Its SKILL.md is about 3.4k 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 and Observability. The repository describes itself as: Universal Claude Code workflow plugin with agents, skills, hooks, and commands. The licence is MIT.

When your agent uses it

  • Designing error handling
  • Setting up logging
  • Implementing retries
  • Adding error tracking

Example prompts

  • “Use the error-handling skill to implement error handling patterns, structured logging, retry strategies, circuit breakers, and graceful degradation”
  • “/error-handling”

Requirements

  • Python 3

What it can do on your machine

Read from SKILL.md and the folder at commit 3b5a89e. 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 3.4k tokens when it runs. Until then it costs about 80 tokens; SKILL.md has 88 words of instructions outside code blocks.

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

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 CloudAI-X/claude-workflow-v2 at commit 3b5a89e, republished under its MIT licence (© CloudAI-X). 88 words, ~3,361 tokens.

Download SKILL.mdSave it as .claude/skills/error-handling/SKILL.md (or your agent's skills folder).
name
error-handling
description
Implements error handling patterns, structured logging, retry strategies, circuit breakers, and graceful degradation. Use when designing error handling, setting up logging, implementing retries, adding error tracking, or when asked about error boundaries, log aggregation, alerting, or resilience patterns.

Error Handling & Observability

When to Load
  • Trigger: Try/catch patterns, retry logic, error responses, circuit breakers, structured logging
  • Skip: No error handling or observability involved in the current task

Error Handling Workflow

Copy this checklist and track progress:

Error Handling Progress:
- [ ] Step 1: Define error taxonomy (categories and severity)
- [ ] Step 2: Implement error handling by layer
- [ ] Step 3: Set up structured logging
- [ ] Step 4: Add retry and circuit breaker patterns
- [ ] Step 5: Configure error tracking service
- [ ] Step 6: Define user-facing error messages
- [ ] Step 7: Validate against anti-patterns checklist

Error Handling Patterns by Language

JavaScript / TypeScript
typescript
// Custom error hierarchy
class AppError extends Error {
  constructor(
    message: string,
    public statusCode: number = 500,
    public code: string = "INTERNAL_ERROR",
    public isOperational: boolean = true,
  ) {
    super(message);
    this.name = this.constructor.name;
  }
}
class NotFoundError extends AppError {
  constructor(resource: string, id: string) {
    super(`${resource} with id ${id} not found`, 404, "NOT_FOUND");
  }
}
class ValidationError extends AppError {
  constructor(public errors: Record<string, string[]>) {
    super("Validation failed", 400, "VALIDATION_ERROR");
  }
}

// WRONG: Swallowing errors silently
try {
  await saveUser(data);
} catch (e) {
  // nothing here -- bug hides forever
}

// WRONG: Catching and re-throwing without context
try {
  await saveUser(data);
} catch (e) {
  throw e; // pointless try/catch
}

// CORRECT: Add context, handle or propagate
try {
  await saveUser(data);
} catch (error) {
  if (error instanceof ValidationError) {
    return res.status(400).json({ errors: error.errors });
  }
  logger.error({ err: error, userId: data.id }, "Failed to save user");
  throw new AppError("Unable to save user", 500, "USER_SAVE_FAILED");
}
Express Global Error Handler
typescript
// Centralized error handler middleware (must have 4 params)
app.use((err: Error, req: Request, res: Response, next: NextFunction) => {
  if (err instanceof AppError) {
    logger.warn(
      { code: err.code, statusCode: err.statusCode, path: req.path },
      "Operational error",
    );
    return res.status(err.statusCode).json({
      error: { code: err.code, message: err.message },
    });
  }

  // Unexpected errors -- these are bugs
  logger.error({ err, path: req.path }, "Unexpected error");
  res.status(500).json({
    error: { code: "INTERNAL_ERROR", message: "An unexpected error occurred" },
  });
});
Python
python
# Custom exception hierarchy
class AppError(Exception):
    def __init__(self, message: str, code: str = "INTERNAL_ERROR", status: int = 500):
        self.message = message
        self.code = code
        self.status = status
        super().__init__(message)

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

class ValidationError(AppError):
    def __init__(self, errors: dict[str, list[str]]):
        self.errors = errors
        super().__init__("Validation failed", "VALIDATION_ERROR", 400)

# WRONG: Bare except
try:
    result = process(data)
except:  # catches SystemExit, KeyboardInterrupt too!
    pass

# CORRECT: Specific exceptions, proper logging
try:
    result = process(data)
except ValidationError as e:
    logger.warning("Validation failed", extra={"errors": e.errors})
    raise
except DatabaseError as e:
    logger.error("Database error during processing", exc_info=True)
    raise AppError("Processing failed", "PROCESS_FAILED") from e
Go
go
// Define sentinel errors and custom types
var (
    ErrNotFound     = errors.New("resource not found")
    ErrUnauthorized = errors.New("unauthorized")
)

type ValidationError struct {
    Field   string
    Message string
}

func (e *ValidationError) Error() string {
    return fmt.Sprintf("validation: %s - %s", e.Field, e.Message)
}

// WRONG: Ignoring errors
data, _ := json.Marshal(user)  // error silently dropped

// WRONG: Only returning error string
if err != nil {
    return fmt.Errorf("failed: %s", err.Error())  // loses error chain
}

// CORRECT: Wrap errors with context
if err != nil {
    return fmt.Errorf("saving user %s: %w", user.ID, err)  // %w preserves chain
}

// CORRECT: Check error types
if errors.Is(err, ErrNotFound) {
    http.Error(w, "Not found", http.StatusNotFound)
    return
}
var valErr *ValidationError
if errors.As(err, &valErr) {
    http.Error(w, valErr.Error(), http.StatusBadRequest)
    return
}

Structured Logging

JSON Log Format
typescript
// WRONG: Unstructured string logs
console.log(`User ${userId} created order ${orderId} at ${new Date()}`);
// Impossible to parse, filter, or aggregate

// CORRECT: Structured JSON logs
import pino from "pino";

const logger = pino({
  level: process.env.LOG_LEVEL || "info",
  formatters: {
    level: (label) => ({ level: label }),
  },
  redact: ["req.headers.authorization", "password", "ssn"],
});
logger.info({
  event: "order_created",
  userId: "123",
  orderId: "456",
  amount: 99.99,
  currency: "USD",
});
// Output: {"level":"info","event":"order_created","userId":"123","orderId":"456",...}
Correlation IDs
typescript
// Middleware to propagate correlation ID across requests
import { randomUUID } from "crypto";
import { AsyncLocalStorage } from "async_hooks";

const asyncStorage = new AsyncLocalStorage<{ correlationId: string }>();

app.use((req, res, next) => {
  const correlationId =
    (req.headers["x-correlation-id"] as string) || randomUUID();
  res.setHeader("x-correlation-id", correlationId);

  asyncStorage.run({ correlationId }, () => next());
});

// Logger automatically includes correlation ID
function getLogger() {
  const store = asyncStorage.getStore();
  return logger.child({ correlationId: store?.correlationId });
}

// Usage in any handler or service
const log = getLogger();
log.info({ event: "payment_processed", amount: 50 });
// Output includes correlationId automatically
Log Levels Guide
TRACE: Extremely detailed (loop iterations, variable values)  -- dev only
DEBUG: Diagnostic info (function entry/exit, state changes)   -- dev/staging
INFO:  Normal operations (request handled, job completed)     -- all envs
WARN:  Unexpected but recoverable (retry succeeded, fallback used)
ERROR: Operation failed (unhandled exception, service down)
FATAL: Application cannot continue (missing config, DB unreachable)

Production default: INFO
Never log: passwords, tokens, PII, credit cards, full request bodies

Error Boundaries and Graceful Degradation

React Error Boundary
tsx
class ErrorBoundary extends React.Component<
  { fallback: React.ReactNode; children: React.ReactNode },
  { hasError: boolean; error?: Error }
> {
  state = { hasError: false, error: undefined };
  static getDerivedStateFromError(error: Error) {
    return { hasError: true, error };
  }
  componentDidCatch(error: Error, info: React.ErrorInfo) {
    logger.error(
      { err: error, componentStack: info.componentStack },
      "React error boundary caught error",
    );
  }
  render() {
    return this.state.hasError ? this.props.fallback : this.props.children;
  }
}

// Usage: wrap sections independently
<ErrorBoundary fallback={<p>Dashboard unavailable</p>}>
  <Dashboard />
</ErrorBoundary>
<ErrorBoundary fallback={<p>Sidebar unavailable</p>}>
  <Sidebar />
</ErrorBoundary>
Service Degradation
typescript
// Graceful degradation: serve stale data when service is down
async function getProductRecommendations(userId: string) {
  try {
    return await recommendationService.get(userId);
  } catch (error) {
    logger.warn(
      { userId, err: error },
      "Recommendation service unavailable, using fallback",
    );
    return getCachedRecommendations(userId) || getDefaultRecommendations();
  }
}

Retry Patterns

Exponential Backoff
typescript
async function withRetry<T>(
  fn: () => Promise<T>,
  options: {
    maxRetries?: number;
    baseDelay?: number;
    maxDelay?: number;
    retryOn?: (error: Error) => boolean;
  } = {},
): Promise<T> {
  const {
    maxRetries = 3,
    baseDelay = 1000,
    maxDelay = 30000,
    retryOn,
  } = options;
  for (let attempt = 0; attempt <= maxRetries; attempt++) {
    try {
      return await fn();
    } catch (error) {
      if (attempt === maxRetries) throw error;
      if (retryOn && !retryOn(error as Error)) throw error;

      const delay = Math.min(
        baseDelay * 2 ** attempt + Math.random() * 1000,
        maxDelay,
      );
      logger.warn({ attempt: attempt + 1, delay }, "Retrying operation");
      await new Promise((r) => setTimeout(r, delay));
    }
  }
  throw new Error("Unreachable");
}

// Usage: retry only on transient errors
const data = await withRetry(
  async () => {
    const res = await fetch("https://api.example.com/data");
    if (res.status >= 500 || res.status === 429)
      throw new Error(`HTTP ${res.status}`);
    return res;
  },
  {
    retryOn: (err) =>
      err instanceof TypeError || err.message.startsWith("HTTP "),
  },
);
Circuit Breaker
typescript
class CircuitBreaker {
  private failures = 0;
  private lastFailure = 0;
  private state: "closed" | "open" | "half-open" = "closed";

  constructor(
    private threshold: number = 5,
    private resetTimeout: number = 60000,
  ) {}

  async execute<T>(fn: () => Promise<T>, fallback?: () => T): Promise<T> {
    if (this.state === "open") {
      if (Date.now() - this.lastFailure > this.resetTimeout) {
        this.state = "half-open";
      } else {
        if (fallback) return fallback();
        throw new Error("Circuit breaker is open");
      }
    }

    try {
      const result = await fn();
      this.failures = 0;
      this.state = "closed";
      return result;
    } catch (error) {
      this.failures++;
      this.lastFailure = Date.now();
      if (this.failures >= this.threshold) this.state = "open";
      if (fallback) return fallback();
      throw error;
    }
  }
}

// Usage: trips open after 5 failures, resets after 30s
const paymentCircuit = new CircuitBreaker(5, 30000);
const result = await paymentCircuit.execute(
  () => paymentService.charge(amount),
  () => ({ queued: true, message: "Payment will be processed shortly" }),
);

Error Tracking Integration

Sentry Setup
typescript
import * as Sentry from "@sentry/node";

Sentry.init({
  dsn: process.env.SENTRY_DSN,
  environment: process.env.NODE_ENV,
  tracesSampleRate: process.env.NODE_ENV === "production" ? 0.1 : 1.0,
  beforeSend(event) {
    // Scrub sensitive data
    if (event.request?.headers) delete event.request.headers["authorization"];
    return event;
  },
});

Sentry.setUser({ id: user.id, email: user.email });
Sentry.captureException(error, {
  tags: { subsystem: "payment", provider: "stripe" },
  extra: { orderId, amount },
});

User-Facing vs Internal Errors

typescript
// Map internal errors to user-friendly messages
const USER_MESSAGES: Record<string, string> = {
  VALIDATION_ERROR: "Please check your input and try again.",
  NOT_FOUND: "The requested resource could not be found.",
  RATE_LIMITED: "Too many requests. Please wait a moment.",
  PAYMENT_FAILED: "Payment could not be processed. Please try another method.",
  INTERNAL_ERROR: "Something went wrong. Please try again later.",
};

function toUserResponse(error: AppError) {
  return {
    error: {
      code: error.code,
      message: USER_MESSAGES[error.code] || USER_MESSAGES["INTERNAL_ERROR"],
    },
  };
}

// WRONG: Exposing internal details to users
res.status(500).json({
  error: 'QueryFailedError: relation "users" does not exist',
  stack: error.stack,
});

// CORRECT: Generic message to user, full details in logs
logger.error({ err: error, query }, "Database query failed");
res.status(500).json(toUserResponse(new AppError("DB error", 500)));

Common Anti-Patterns Summary

AVOID                              DO INSTEAD
-------------------------------------------------------------------
Empty catch blocks                 Log and handle or re-throw
Bare `except:` in Python           Catch specific exceptions
console.log for production         Structured logger (pino, winston)
Logging passwords/tokens           Redact sensitive fields
Retry without backoff              Exponential backoff with jitter
Retry on all errors                Only retry transient/network errors
No circuit breaker                 Circuit breaker for external calls
Exposing stack traces to users     Generic user messages, detailed logs
No correlation IDs                 Propagate correlation ID across services
One giant try/catch                Granular error handling per operation
Logging inside tight loops         Log summaries/aggregates
No error boundaries in React       Wrap independent sections separately

© CloudAI-X, 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 CloudAI-X/claude-workflow-v2.

Open the folder on GitHubat commit 3b5a89e

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 skillCloudAI-X/claude-workflow-v21.4k—~3.4kAutomated safety check: PassMIT
Logging Observabilitygetsentry/toolkit917—~2.6kAutomated safety check: PassCustom licence
evlog Map Rule Creatorevloghq/evlog1.9k—~2.9kAutomated safety check: PassMIT
fp-go Logging PatternsIBM/fp-go2k—~3.7kAutomated safety check: PassApache-2.0
Rust SkillsJMBeresford/retrom2.1k1 repos~9.5kAutomated safety check: PassMIT
Crash Instrumentationnexus-labs-automation/mobile-observability116—~744Automated safety check: PassMIT

Similar skills

  • Logging Observability

    getsentry/toolkit

    Official

    Review code for correct logging and error handling patterns.

    917 GitHub stars~2.6k tokensUpdated today
    DevOps & CloudAuto-check passed
  • Walks through adding a new rule or framework adapter to `evlog map` in @evlog/cli, from the rule source and registry to types, tests, docs and the published skill.

    1.9k GitHub stars~2.9k tokensUpdated yesterday
    DevelopmentAuto-check passed
  • Official

    Adds logging to fp-go functional pipelines with Tap operators, entry and exit logs and error context, so that logging never changes the value or error flowing through.

    2k GitHub stars~3.7k tokensUpdated yesterday
    DevelopmentAuto-check passed
  • Rust Skills

    JMBeresford/retrom

    Comprehensive Rust coding guidelines with 265 rules across 26 categories.

    2.1k GitHub starsUsed in 1 repo~9.5k tokens
    DevelopmentAuto-check passed
  • Crash Instrumentation

    nexus-labs-automation/mobile-observability

    Set up crash instrumentation with actionable context. An agent skill from nexus-labs-automation/mobile-observability.

    116 GitHub stars~744 tokensUpdated 1 mo ago
    DevOps & CloudAuto-check passed
  • Guides log level choices and when to raise a structured Sentry event instead of a plain log line in the Warp Rust codebase, keeping secrets out of logs.

    65k GitHub starsUsed in 1 repo~5.6k tokens
    DevelopmentAuto-check passed

More from CloudAI-X/claude-workflow-v2

All 13 skills in this repo
  • Analyzing Projects

    CloudAI-X/claude-workflow-v2

    Analyzes codebases to understand structure, tech stack, patterns, and conventions.

    1.4k GitHub starsUsed in 2 repos~937 tokens
    Auto-check passed
  • Designing APIs

    CloudAI-X/claude-workflow-v2

    Designs REST and GraphQL APIs including endpoints, error handling, versioning, and documentation.

    1.4k GitHub starsUsed in 2 repos~1.2k tokens
    Auto-check passed
  • Designing Architecture

    CloudAI-X/claude-workflow-v2

    Designs software architecture and selects appropriate patterns for projects.

    1.4k GitHub starsUsed in 1 repo~1.4k tokens
    Auto-check passed
  • Designing Tests

    CloudAI-X/claude-workflow-v2

    Designs and implements testing strategies for any codebase. An agent skill from CloudAI-X/claude-workflow-v2.

    1.4k GitHub starsUsed in 1 repo~1.5k tokens
    Auto-check passed
  • Managing Git

    CloudAI-X/claude-workflow-v2

    Manages Git workflows including branching, commits, and pull requests.

    1.4k GitHub starsUsed in 1 repo~1.3k tokens
    Auto-check passed
  • Optimizing Performance

    CloudAI-X/claude-workflow-v2

    Analyzes and optimizes application performance across frontend, backend, and database layers.

    1.4k GitHub starsUsed in 1 repo~1.5k tokens
    Auto-check passed

Questions about Error Handling

What does Error Handling do?

Implements error handling patterns, structured logging, retry strategies, circuit breakers, and graceful degradation. Error Handling is an agent skill from CloudAI-X/claude-workflow-v2. Implements error handling patterns, structured logging, retry strategies, circuit breakers, and graceful degradation.

When should I use Error Handling?

Error Handling fits situations like: designing error handling; setting up logging; implementing retries; adding error tracking.

How do I install Error Handling in Claude Code?

Run `npx skills add CloudAI-X/claude-workflow-v2 --skill error-handling -a claude-code`. Or copy the skill folder (skills/error-handling in CloudAI-X/claude-workflow-v2) 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 CloudAI-X/claude-workflow-v2 --skill error-handling -a codex`. Or copy the skill folder (skills/error-handling in CloudAI-X/claude-workflow-v2) 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 CloudAI-X/claude-workflow-v2 --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 3.4k tokens (SKILL.md is roughly 13k 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: Logging Observability (getsentry/toolkit, 917 stars), evlog Map Rule Creator (evloghq/evlog, 1.9k stars), fp-go Logging Patterns (IBM/fp-go, 2k stars) and Rust Skills (JMBeresford/retrom, 2.1k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Error Handling?

CloudAI-X (a GitHub user) maintains it in CloudAI-X/claude-workflow-v2, which has 1,418 GitHub stars. The repository holds 13 skills in this directory. The repository was last updated on October 6, 2026.

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