Skip to main content
skill CX Codex

api-error-handling — Claude Code skill: one error format for your API

The skill sets a standard error response shape, an ApiError class and a circuit breaker. Useful once your API hits production.

Install into Claude Code · Skills CLI (Vercel) All methods and platforms ↓
npx skills add secondsky/claude-skills --skill api-error-handling -a claude-code
Open on GitHub

What api-error-handling does

Every error response follows the same JSON shape: a code, a message, the HTTP status, a requestId, a timestamp and optional field-level details. Clients get one thing to parse, and you get a request ID to grep for when something breaks.

The skill ships an ApiError class for Node.js with badRequest, notFound and unauthorized helpers, a global Express error handler, and a circuit breaker that trips after a set number of failures and moves to half-open after a timeout. A pointer leads to references/python-flask.md for Flask exceptions, retries with exponential backoff and Sentry wiring.

One behaviour to plan around: at status 500 the handler replaces the message with a generic one and logs the real error. If your current code returns exception text to clients, that changes. The examples target Node.js and Express; Python lives in the references file.

What it helps with

  • keep error responses consistent across every endpoint
  • send clients a readable message instead of a stack trace
  • tie an error back to a specific request with requestId
  • return validation failures broken down by field
  • stop hammering a failing upstream service

Example prompts for the agent

  • Add error handling to this Express router using the format from the api-error-handling skill
  • Create an ApiError class and a global handler so 500s never leak the exception text
  • Wrap the payment API call in a circuit breaker with a threshold of 5 failures

How to install api-error-handling

1Skills CLI (Vercel)

npx skills add secondsky/claude-skills --skill api-error-handling -a claude-code

2Manually: put the files in place

~/.claude/skills/api-error-handling/SKILL.md

Copy the whole skill folder; for one project use .claude/skills/api-error-handling/

Step by step, with commands for each platform: How to install skills in Claude Code: five ways

Questions about api-error-handling

How do I install api-error-handling in Claude?

Run npx skills add secondsky/claude-skills --skill api-error-handling -a claude-code. The skill then lives at ~/.claude/skills/api-error-handling/SKILL.md.

What does api-error-handling do?

It defines a standard error response with a code, status and requestId, plus an ApiError class for Node.js, a global Express handler and a circuit breaker pattern.

Which languages are covered?

The main examples are Node.js with Express. Python gets its own file, references/python-flask.md, covering Flask exceptions, retries and Sentry integration.

Source text

SKILL.md · MIT
---
name: api-error-handling
description: Implements standardized API error responses with proper status codes, logging, and user-friendly messages. Use when building production APIs, implementing error recovery patterns, or integrating error monitoring services.
license: MIT
---

# API Error Handling

Implement robust error handling with standardized responses and proper logging.

## Standard Error Response Format

```json
{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Invalid request parameters",
    "status": 400,
    "requestId": "req_abc123",
    "timestamp": "2025-01-15T10:30:00Z",
    "details": [
      { "field": "email", "message": "Invalid email format" }
    ]
  }
}
```

## Error Class (Node.js)

```javascript
class ApiError extends Error {
  constructor(code, message, status = 500, details = null) {
    super(message);
    this.code = code;
    this.status = status;
    this.details = details;
  }

  static badRequest(message, details) {
    return new ApiError('BAD_REQUEST', message, 400, details);
  }

  static notFound(resource) {
    return new ApiError('NOT_FOUND', `${resource} not found`, 404);
  }

  static unauthorized() {
    return new ApiError('UNAUTHORIZED', 'Authentication required', 401);
  }
}

// Global error handler
app.use((err, req, res, next) => {
  const status = err.status || 500;
  const response = {
    error: {
      code: err.code || 'INTERNAL_ERROR',
      message: status === 500 ? 'Internal server error' : err.message,
      status,
      requestId: req.id
    }
  };

  if (err.details) response.error.details = err.details;
  if (status >= 500) logger.error(err);

  res.status(status).json(response);
});
```

## Circuit Breaker Pattern

```javascript
class CircuitBreaker {
  constructor(threshold = 5, timeout = 30000) {
    this.failures = 0;
    this.threshold = threshold;
    this.timeout = timeout;
    this.state = 'CLOSED';
  }

  async call(fn) {
    if (this.state === 'OPEN') throw new Error('Circuit open');
    try {
      const result = await fn();
      this.failures = 0;
      return result;
    } catch (err) {
      this.failures++;
      if (this.failures >= this.threshold) {
        this.state = 'OPEN';
        setTimeout(() => this.state = 'HALF_OPEN', this.timeout);
      }
      throw err;
    }
  }
}
```

## Additional Implementations

See [references/python-flask.md](references/python-flask.md) for:
- Python Flask error handling with custom exceptions
- Circuit breaker with automatic recovery
- Retry with exponential backoff
- Sentry integration

## Best Practices

- Use consistent error format across all endpoints
- Include request IDs for traceability
- Log errors at appropriate severity levels
- Never expose stack traces to clients
- Distinguish client errors (4xx) from server errors (5xx)
- Provide actionable error messages

© secondsky · MIT · secondsky/claude-skills

Similar skills

Everything for Backend and APIs →

From the same set89

Project sponsors

Companies that keep this analytics open
Gold sponsor

Impressions, clicks and code copies — open statistics. We keep the numbers public for the same reason NeBlask itself is public. Become a sponsor