Error handling patterns across languages and layers — operational vs programmer errors, retry strategies, circuit breakers, error boundaries, HTTP responses, graceful degradation, and structured logging. Use when designing error strategies, building resilient APIs, or reviewing error management.
数据来源:ClawHub。 在 ClawSkills 查看
选择你使用的 Agent
方法一:命令行安装(推荐)
推荐(无需提前安装 clawhub)
npx clawhub@latest --dir ~/.claude/skills install api-error-handling或使用 clawhub CLI(需提前安装)
clawhub --dir ~/.claude/skills install api-error-handling⚠️ 需要 Node.js 18+,没有 Node?请使用下方方法二直接下载 ZIP。 安装 Node.js →
方法二:手动下载安装(无需 Node)
下载 ZIP,解压后将文件夹放到以下路径,重启 Agent 即可:
安装路径
~/.claude/skills/api-error-handling/💡解压后将文件夹放到上方路径,重启 Agent 即可生效
--- name: error-handling model: standard description: Error handling patterns across languages and layers — operational vs programmer errors, retry strategies, circuit breakers, error boundaries, HTTP responses, graceful degradation, and structured logging. Use when designing error strategies, building resilient APIs, or reviewing error management. ---
> Ship resilient software. Handle errors at boundaries, fail fast and loud, never swallow exceptions silently.
| Principle | Description | |-----------|-------------| | Fail Fast | Detect errors early — validate inputs at the boundary, not deep in business logic | | Fail Loud | Errors must be visible — log them, surface them, alert on them | | Handle at Boundaries | Catch and translate errors at layer boundaries (controller, middleware, gateway) | | Let It Crash | For unrecoverable state, crash and restart (Erlang/OTP philosophy) | | Be Specific | Catch specific error types, never bare catch or except | | Provide Context | Every error carries enough context to diagnose without reproducing |
---
Operational errors — network timeouts, invalid user input, file not found, DB connection lost. Handle gracefully.
Programmer errors — TypeError, null dereference, assertion failures. Fix the code — don't catch and suppress.
// Operational — handle gracefully
try {
const data = await fetch('/api/users');
} catch (err) {
if (err.code === 'ECONNREFUSED') return fallbackData;
throw err; // re-throw unexpected errors
}
// Programmer — let it crash, fix the bug
const user = null;
user.name; // TypeError — don't try/catch this
---
| Language | Mechanism | Anti-Pattern | |----------|-----------|-------------| | JavaScript | try/catch, Promise.catch, Error subclasses | .catch(() => {}) swallowing errors | | Python | Exceptions, context managers (with) | Bare except: catching everything | | Go | error returns, errors.Is/As, fmt.Errorf wrapping | _ = riskyFunction() ignoring error | | Rust | Result, Option, ? operator | .unwrap() in production code |
class AppError extends Error {
constructor(message, code, statusCode, details = {}) {
super(message);
this.name = this.constructor.name;
this.code = code;
this.statusCode = statusCode;
this.details = details;
this.isOperational = true;
}
}
class NotFoundError extends AppError {
constructor(resource, id) {
super(`${resource} not found`, 'NOT_FOUND', 404, { resource, id });
}
}
class ValidationError extends AppError {
constructor(errors) {
super('Validation failed', 'VALIDATION_ERROR', 422, { errors });
}
}
func GetUser(id string) (*User, error) {
row := db.QueryRow("SELECT * FROM users WHERE id = $1", id)
var user User
if err := row.Scan(&user.ID, &user.Name); err != nil {
if errors.Is(err, sql.ErrNoRows) {
return nil, fmt.Errorf("user %s: %w", id, ErrNotFound)
}
return nil, fmt.Errorf("querying user %s: %w", id, err)
}
return &user, nil
}
---
app.use((err, req, res, next) => {
const statusCode = err.statusCode || 500;
const response = {
error: {
code: err.code || 'INTERNAL_ERROR',
message: err.isOperational ? err.message : 'Something went wrong',
...(process.env.NODE_ENV === 'development' && { stack: err.stack }),
requestId: req.id,
},
};
logger.error('Request failed', {
err, requestId: req.id, method: req.method, path: req.path,
});
res.status(statusCode).json(response);
});
import { ErrorBoundary } from 'react-error-boundary';
function ErrorFallback({ error, resetErrorBoundary }) {
return (
<div role="alert">
<h2>Something went wrong</h2>
<pre>{error.message}</pre>
<button onClick={resetErrorBoundary}>Try again</button>
</div>
);
}
<ErrorBoundary FallbackComponent={ErrorFallback} onReset={() => queryClient.clear()}>
<App />
</ErrorBoundary>
---
| Pattern | When to Use | Config | |---------|-------------|--------| | Exponential Backoff | Transient failures (network, 503) | Base 1s, max 30s, factor 2x | | Backoff + Jitter | Multiple clients retrying | Random ±30% on each delay | | Circuit Breaker | Downstream service failing repeatedly | Open after 5 failures, half-open after 30s | | Bulkhead | Isolate failures to prevent cascade | Limit concurrent calls per service | | Timeout | Prevent indefinite hangs | Connect 5s, read 30s, total 60s |
async function withRetry(fn, { maxRetries = 3, baseDelay = 1000, maxDelay = 30000 } = {}) {
for (let attempt = 0; attempt <= maxRetries; attempt++) {
try {
return await fn();
} catch (err) {
if (attempt === maxRetries || !isRetryable(err)) throw err;
const delay = Math.min(baseDelay * 2 ** attempt, maxDelay);
const jitter = delay * (0.7 + Math.random() * 0.6);
await new Promise((r) => setTimeout(r, jitter));
}
}
}
function isRetryable(err) {
return [408, 429, 500, 502, 503, 504].includes(err.statusCode) || err.code === 'ECONNRESET';
}
class CircuitBreaker {
constructor({ threshold = 5, resetTimeout = 30000 } = {}) {
this.state = 'CLOSED'; // CLOSED → OPEN → HALF_OPEN → CLOSED
this.failureCount = 0;
this.threshold = threshold;
this.resetTimeout = resetTimeout;
this.nextAttempt = 0;
}
async call(fn) {
if (this.state === 'OPEN') {
if (Date.now() < this.nextAttempt) throw new Error('Circuit is OPEN');
this.state = 'HALF_OPEN';
}
try {
const result = await fn();
this.onSuccess();
return result;
} catch (err) {
this.onFailure();
throw err;
}
}
onSuccess() { this.failureCount = 0; this.state = 'CLOSED'; }
onFailure() {
this.failureCount++;
if (this.failureCount >= this.threshold) {
this.state = 'OPEN';
this.nextAttempt = Date.now() + this.resetTimeout;
}
}
}
---
| Status | Name | When to Use | |--------|------|-------------| | 400 | Bad Request | Malformed syntax, invalid JSON | | 401 | Unauthorized | Missing or invalid authentication | | 403 | Forbidden | Authenticated but insufficient permissions | | 404 | Not Found | Resource does not exist | | 409 | Conflict | Request conflicts with current state | | 422 | Unprocessable Entity | Valid syntax but semantic errors | | 429 | Too Many Requests | Rate limit exceeded (include Retry-After) | | 500 | Internal Server Error | Unexpected server failure | | 502 | Bad Gateway | Upstream returned invalid response | | 503 | Service Unavailable | Temporarily overloaded or maintenance |
{
"error": {
"code": "VALIDATION_ERROR",
"message": "The request body contains invalid fields.",
"details": [
{ "field": "email", "message": "Must be a valid email address" }
],
"requestId": "req_abc123xyz"
}
}
---
| Strategy | Example | |----------|---------| | Fallback values | Show cached avatar when image service is down | | Feature flags | Disable unstable recommendation engine | | Cached responses | Serve stale data with X-Cache: STALE header | | Partial response | Return available data with warnings array |
async function getProductPage(productId) {
const product = await productService.get(productId); // critical — propagate errors
...安装 API Error Handling 后,可以对 AI 说这些话来触发它
Help me get started with API Error Handling
Explains what API Error Handling does, walks through the setup, and runs a quick demo based on your current project
Use API Error Handling to error handling patterns across languages and layers — operational v...
Invokes API Error Handling with the right parameters and returns the result directly in the conversation
What can I do with API Error Handling in my developer & devops workflow?
Lists the top use cases for API Error Handling, with example commands for each scenario
将技能文件夹放到 ~/.claude/skills/api-error-handling/ 目录(个人级,所有项目可用),或 .claude/skills/api-error-handling/(项目级)。重启 AI 客户端后,用 /api-error-handling 主动调用,或让 AI 根据上下文自动发现并使用。
API Error Handling 支持 Claude、Cursor、OpenClaw,可与这些 AI 平台无缝集成,扩展其能力。
API Error Handling 可免费安装使用。请查阅仓库了解许可证信息。
Error handling patterns across languages and layers — operational vs programmer errors, retry strategies, circuit breakers, error boundaries, HTTP responses, graceful degradation, and structured logging. Use when designing error strategies, building resilient APIs, or reviewing error management.
Automate my developer & devops tasks using API Error Handling
Identifies repetitive steps in your workflow and sets up API Error Handling to handle them automatically
API Error Handling 属于「Developer & DevOps」分类,该分类的技能帮助 AI 智能体在此领域执行专业任务。