{"id":"9305e1f2-2caa-4dad-94bd-926c238ad18a","shortId":"WMRrxq","kind":"skill","title":"error-handling","tagline":"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, alertin","description":"# Error Handling & Observability\n\n### When to Load\n\n- **Trigger**: Try/catch patterns, retry logic, error responses, circuit breakers, structured logging\n- **Skip**: No error handling or observability involved in the current task\n\n## Error Handling Workflow\n\nCopy this checklist and track progress:\n\n```\nError Handling Progress:\n- [ ] Step 1: Define error taxonomy (categories and severity)\n- [ ] Step 2: Implement error handling by layer\n- [ ] Step 3: Set up structured logging\n- [ ] Step 4: Add retry and circuit breaker patterns\n- [ ] Step 5: Configure error tracking service\n- [ ] Step 6: Define user-facing error messages\n- [ ] Step 7: Validate against anti-patterns checklist\n```\n\n## Error Handling Patterns by Language\n\n### JavaScript / TypeScript\n\n```typescript\n// Custom error hierarchy\nclass AppError extends Error {\n  constructor(\n    message: string,\n    public statusCode: number = 500,\n    public code: string = \"INTERNAL_ERROR\",\n    public isOperational: boolean = true,\n  ) {\n    super(message);\n    this.name = this.constructor.name;\n  }\n}\nclass NotFoundError extends AppError {\n  constructor(resource: string, id: string) {\n    super(`${resource} with id ${id} not found`, 404, \"NOT_FOUND\");\n  }\n}\nclass ValidationError extends AppError {\n  constructor(public errors: Record<string, string[]>) {\n    super(\"Validation failed\", 400, \"VALIDATION_ERROR\");\n  }\n}\n\n// WRONG: Swallowing errors silently\ntry {\n  await saveUser(data);\n} catch (e) {\n  // nothing here -- bug hides forever\n}\n\n// WRONG: Catching and re-throwing without context\ntry {\n  await saveUser(data);\n} catch (e) {\n  throw e; // pointless try/catch\n}\n\n// CORRECT: Add context, handle or propagate\ntry {\n  await saveUser(data);\n} catch (error) {\n  if (error instanceof ValidationError) {\n    return res.status(400).json({ errors: error.errors });\n  }\n  logger.error(\"Failed to save user\", { error, userId: data.id });\n  throw new AppError(\"Unable to save user\", 500, \"USER_SAVE_FAILED\");\n}\n```\n\n### Express Global Error Handler\n\n```typescript\n// Centralized error handler middleware (must have 4 params)\napp.use((err: Error, req: Request, res: Response, next: NextFunction) => {\n  if (err instanceof AppError) {\n    logger.warn(\"Operational error\", {\n      code: err.code,\n      statusCode: err.statusCode,\n      path: req.path,\n    });\n    return res.status(err.statusCode).json({\n      error: { code: err.code, message: err.message },\n    });\n  }\n\n  // Unexpected errors -- these are bugs\n  logger.error(\"Unexpected error\", {\n    error: err.message,\n    stack: err.stack,\n    path: req.path,\n  });\n  res.status(500).json({\n    error: { code: \"INTERNAL_ERROR\", message: \"An unexpected error occurred\" },\n  });\n});\n```\n\n### Python\n\n```python\n# Custom exception hierarchy\nclass AppError(Exception):\n    def __init__(self, message: str, code: str = \"INTERNAL_ERROR\", status: int = 500):\n        self.message = message\n        self.code = code\n        self.status = status\n        super().__init__(message)\n\nclass NotFoundError(AppError):\n    def __init__(self, resource: str, id: str):\n        super().__init__(f\"{resource} {id} not found\", \"NOT_FOUND\", 404)\n\nclass ValidationError(AppError):\n    def __init__(self, errors: dict[str, list[str]]):\n        self.errors = errors\n        super().__init__(\"Validation failed\", \"VALIDATION_ERROR\", 400)\n\n# WRONG: Bare except\ntry:\n    result = process(data)\nexcept:  # catches SystemExit, KeyboardInterrupt too!\n    pass\n\n# CORRECT: Specific exceptions, proper logging\ntry:\n    result = process(data)\nexcept ValidationError as e:\n    logger.warning(\"Validation failed\", extra={\"errors\": e.errors})\n    raise\nexcept DatabaseError as e:\n    logger.error(\"Database error during processing\", exc_info=True)\n    raise AppError(\"Processing failed\", \"PROCESS_FAILED\") from e\n```\n\n### Go\n\n```go\n// Define sentinel errors and custom types\nvar (\n    ErrNotFound     = errors.New(\"resource not found\")\n    ErrUnauthorized = errors.New(\"unauthorized\")\n)\n\ntype ValidationError struct {\n    Field   string\n    Message string\n}\n\nfunc (e *ValidationError) Error() string {\n    return fmt.Sprintf(\"validation: %s - %s\", e.Field, e.Message)\n}\n\n// WRONG: Ignoring errors\ndata, _ := json.Marshal(user)  // error silently dropped\n\n// WRONG: Only returning error string\nif err != nil {\n    return fmt.Errorf(\"failed: %s\", err.Error())  // loses error chain\n}\n\n// CORRECT: Wrap errors with context\nif err != nil {\n    return fmt.Errorf(\"saving user %s: %w\", user.ID, err)  // %w preserves chain\n}\n\n// CORRECT: Check error types\nif errors.Is(err, ErrNotFound) {\n    http.Error(w, \"Not found\", http.StatusNotFound)\n    return\n}\nvar valErr *ValidationError\nif errors.As(err, &valErr) {\n    http.Error(w, valErr.Error(), http.StatusBadRequest)\n    return\n}\n```\n\n## Structured Logging\n\n### JSON Log Format\n\n```typescript\n// WRONG: Unstructured string logs\nconsole.log(`User ${userId} created order ${orderId} at ${new Date()}`);\n// Impossible to parse, filter, or aggregate\n\n// CORRECT: Structured JSON logs\nimport pino from \"pino\";\n\nconst logger = pino({\n  level: process.env.LOG_LEVEL || \"info\",\n  formatters: {\n    level: (label) => ({ level: label }),\n  },\n  redact: [\"req.headers.authorization\", \"password\", \"ssn\"],\n});\nlogger.info({\n  event: \"order_created\",\n  userId: \"123\",\n  orderId: \"456\",\n  amount: 99.99,\n  currency: \"USD\",\n});\n// Output: {\"level\":\"info\",\"event\":\"order_created\",\"userId\":\"123\",\"orderId\":\"456\",...}\n```\n\n### Correlation IDs\n\n```typescript\n// Middleware to propagate correlation ID across requests\nimport { randomUUID } from \"crypto\";\nimport { AsyncLocalStorage } from \"async_hooks\";\n\nconst asyncStorage = new AsyncLocalStorage<{ correlationId: string }>();\n\napp.use((req, res, next) => {\n  const correlationId =\n    (req.headers[\"x-correlation-id\"] as string) || randomUUID();\n  res.setHeader(\"x-correlation-id\", correlationId);\n\n  asyncStorage.run({ correlationId }, () => next());\n});\n\n// Logger automatically includes correlation ID\nfunction getLogger() {\n  const store = asyncStorage.getStore();\n  return logger.child({ correlationId: store?.correlationId });\n}\n\n// Usage in any handler or service\nconst log = getLogger();\nlog.info({ event: \"payment_processed\", amount: 50 });\n// Output includes correlationId automatically\n```\n\n### Log Levels Guide\n\n```\nTRACE: Extremely detailed (loop iterations, variable values)  -- dev only\nDEBUG: Diagnostic info (function entry/exit, state changes)   -- dev/staging\nINFO:  Normal operations (request handled, job completed)     -- all envs\nWARN:  Unexpected but recoverable (retry succeeded, fallback used)\nERROR: Operation failed (unhandled exception, service down)\nFATAL: Application cannot continue (missing config, DB unreachable)\n\nProduction default: INFO\nNever log: passwords, tokens, PII, credit cards, full request bodies\n```\n\n## Error Boundaries and Graceful Degradation\n\n### React Error Boundary\n\n```tsx\nclass ErrorBoundary extends React.Component<\n  { fallback: React.ReactNode; children: React.ReactNode },\n  { hasError: boolean; error?: Error }\n> {\n  state = { hasError: false, error: undefined };\n  static getDerivedStateFromError(error: Error) {\n    return { hasError: true, error };\n  }\n  componentDidCatch(error: Error, info: React.ErrorInfo) {\n    logger.error(\"React error boundary caught error\", {\n      error: error.message,\n      componentStack: info.componentStack,\n    });\n  }\n  render() {\n    return this.state.hasError ? this.props.fallback : this.props.children;\n  }\n}\n\n// Usage: wrap sections independently\n<ErrorBoundary fallback={<p>Dashboard unavailable</p>}>\n  <Dashboard />\n</ErrorBoundary>\n<ErrorBoundary fallback={<p>Sidebar unavailable</p>}>\n  <Sidebar />\n</ErrorBoundary>\n```\n\n### Service Degradation\n\n```typescript\n// Graceful degradation: serve stale data when service is down\nasync function getProductRecommendations(userId: string) {\n  try {\n    return await recommendationService.get(userId);\n  } catch (error) {\n    logger.warn(\"Recommendation service unavailable, using fallback\", {\n      userId,\n      error: error.message,\n    });\n    return getCachedRecommendations(userId) || getDefaultRecommendations();\n  }\n}\n```\n\n## Retry Patterns\n\n### Exponential Backoff\n\n```typescript\nasync function withRetry<T>(\n  fn: () => Promise<T>,\n  options: {\n    maxRetries?: number;\n    baseDelay?: number;\n    maxDelay?: number;\n    retryOn?: (error: Error) => boolean;\n  } = {},\n): Promise<T> {\n  const {\n    maxRetries = 3,\n    baseDelay = 1000,\n    maxDelay = 30000,\n    retryOn,\n  } = options;\n  for (let attempt = 0; attempt <= maxRetries; attempt++) {\n    try {\n      return await fn();\n    } catch (error) {\n      if (attempt === maxRetries) throw error;\n      if (retryOn && !retryOn(error as Error)) throw error;\n\n      const delay = Math.min(\n        baseDelay * 2 ** attempt + Math.random() * 1000,\n        maxDelay,\n      );\n      logger.warn(\"Retrying operation\", { attempt: attempt + 1, delay });\n      await new Promise((r) => setTimeout(r, delay));\n    }\n  }\n  throw new Error(\"Unreachable\");\n}\n\n// Usage: retry only on transient errors\nconst data = await withRetry(() => fetch(\"https://api.example.com/data\"), {\n  retryOn: (err) => err.message.includes(\"ECONNRESET\"),\n});\n```\n\n### Circuit Breaker\n\n```typescript\nclass CircuitBreaker {\n  private failures = 0;\n  private lastFailure = 0;\n  private state: \"closed\" | \"open\" | \"half-open\" = \"closed\";\n\n  constructor(\n    private threshold: number = 5,\n    private resetTimeout: number = 60000,\n  ) {}\n\n  async execute<T>(fn: () => Promise<T>, fallback?: () => T): Promise<T> {\n    if (this.state === \"open\") {\n      if (Date.now() - this.lastFailure > this.resetTimeout) {\n        this.state = \"half-open\";\n      } else {\n        if (fallback) return fallback();\n        throw new Error(\"Circuit breaker is open\");\n      }\n    }\n\n    try {\n      const result = await fn();\n      this.failures = 0;\n      this.state = \"closed\";\n      return result;\n    } catch (error) {\n      this.failures++;\n      this.lastFailure = Date.now();\n      if (this.failures >= this.threshold) this.state = \"open\";\n      if (fallback) return fallback();\n      throw error;\n    }\n  }\n}\n\n// Usage: trips open after 5 failures, resets after 30s\nconst paymentCircuit = new CircuitBreaker(5, 30000);\nconst result = await paymentCircuit.execute(\n  () => paymentService.charge(amount),\n  () => ({ queued: true, message: \"Payment will be processed shortly\" }),\n);\n```\n\n## Error Tracking Integration\n\n### Sentry Setup\n\n```typescript\nimport * as Sentry from \"@sentry/node\";\n\nSentry.init({\n  dsn: process.env.SENTRY_DSN,\n  environment: process.env.NODE_ENV,\n  tracesSampleRate: process.env.NODE_ENV === \"production\" ? 0.1 : 1.0,\n  beforeSend(event) {\n    // Scrub sensitive data\n    if (event.request?.headers) delete event.request.headers[\"authorization\"];\n    return event;\n  },\n});\n\nSentry.setUser({ id: user.id, email: user.email });\nSentry.captureException(error, {\n  tags: { subsystem: \"payment\", provider: \"stripe\" },\n  extra: { orderId, amount },\n});\n```\n\n## User-Facing vs Internal Errors\n\n```typescript\n// Map internal errors to user-friendly messages\nconst USER_MESSAGES: Record<string, string> = {\n  VALIDATION_ERROR: \"Please check your input and try again.\",\n  NOT_FOUND: \"The requested resource could not be found.\",\n  RATE_LIMITED: \"Too many requests. Please wait a moment.\",\n  PAYMENT_FAILED: \"Payment could not be processed. Please try another method.\",\n  INTERNAL_ERROR: \"Something went wrong. Please try again later.\",\n};\n\nfunction toUserResponse(error: AppError) {\n  return {\n    error: {\n      code: error.code,\n      message: USER_MESSAGES[error.code] || USER_MESSAGES[\"INTERNAL_ERROR\"],\n    },\n  };\n}\n\n// WRONG: Exposing internal details to users\nres.status(500).json({\n  error: 'QueryFailedError: relation \"users\" does not exist',\n  stack: error.stack,\n});\n\n// CORRECT: Generic message to user, full details in logs\nlogger.error(\"Database query failed\", {\n  error: error.message,\n  stack: error.stack,\n  query,\n});\nres.status(500).json(toUserResponse(new AppError(\"DB error\", 500)));\n```\n\n## Common Anti-Patterns Summary\n\n```\nAVOID                              DO INSTEAD\n-------------------------------------------------------------------\nEmpty catch blocks                 Log and handle or re-throw\nBare `except:` in Python           Catch specific exceptions\nconsole.log for production         Structured logger (pino, winston)\nLogging passwords/tokens           Redact sensitive fields\nRetry without backoff              Exponential backoff with jitter\nRetry on all errors                Only retry transient/network errors\nNo circuit breaker                 Circuit breaker for external calls\nExposing stack traces to users     Generic user messages, detailed logs\nNo correlation IDs                 Propagate correlation ID across services\nOne giant try/catch                Granular error handling per operation\nLogging inside tight loops         Log summaries/aggregates\nNo error boundaries in React       Wrap independent sections separately\n```","tags":["error","handling","claude","workflow","cloudai-x","agent-skills","ai-agents","claude-code","codex","cursor","skills"],"capabilities":["skill","source-cloudai-x","skill-error-handling","topic-agent-skills","topic-ai-agents","topic-claude-code","topic-codex","topic-cursor","topic-skills","topic-workflow"],"categories":["claude-workflow-v2"],"synonyms":[],"warnings":[],"endpointUrl":"https://skills.sh/CloudAI-X/claude-workflow-v2/error-handling","protocol":"skill","transport":"skills-sh","auth":{"type":"none","details":{"cli":"npx skills add CloudAI-X/claude-workflow-v2","source_repo":"https://github.com/CloudAI-X/claude-workflow-v2","install_from":"skills.sh"}},"qualityScore":"0.700","qualityRationale":"deterministic score 0.70 from registry signals: · indexed on github topic:agent-skills · 1352 github stars · SKILL.md body (13,006 chars)","verified":false,"liveness":"unknown","lastLivenessCheck":null,"agentReviews":{"count":0,"score_avg":null,"cost_usd_avg":null,"success_rate":null,"latency_p50_ms":null,"narrative_summary":null,"summary_updated_at":null},"enrichmentModel":"deterministic:skill-github:v1","enrichmentVersion":1,"enrichedAt":"2026-05-03T00:52:55.946Z","embedding":null,"createdAt":"2026-04-18T21:54:56.451Z","updatedAt":"2026-05-03T00:52:55.946Z","lastSeenAt":"2026-05-03T00:52:55.946Z","tsv":"'/data':990 '0':927,1002,1005,1059 '0.1':1131 '1':80,964 '1.0':1132 '1000':919,957 '123':626,640 '2':88,954 '3':95,917 '30000':921,1094 '30s':1088 '4':101,285 '400':197,251,412 '404':181,392 '456':628,642 '5':109,1018,1084,1093 '50':720 '500':151,270,333,363,1252,1282,1289 '6':115 '60000':1022 '7':123 '99.99':630 'across':651,1366 'ad':27 'add':102,234 'aggreg':37,596 'alertin':38 'amount':629,719,1100,1160 'anoth':1218 'anti':127,1292 'anti-pattern':126,1291 'api.example.com':989 'api.example.com/data':988 'app.use':287,668 'apperror':142,168,187,265,299,350,375,395,459,1232,1286 'applic':770 'ask':32 'async':660,868,898,1023 'asynclocalstorag':658,665 'asyncstorag':663 'asyncstorage.getstore':700 'asyncstorage.run':688 'attempt':926,928,930,938,955,962,963 'author':1143 'automat':692,724 'avoid':1295 'await':205,224,240,875,933,966,985,1056,1097 'backoff':896,1329,1331 'bare':414,1308 'basedelay':906,918,953 'beforesend':1133 'block':1300 'bodi':789 'boolean':159,808,913 'boundari':35,791,797,832,1384 'breaker':13,53,106,996,1050,1344,1346 'bug':212,322 'call':1349 'cannot':771 'card':786 'catch':208,216,227,243,421,878,935,1064,1299,1312 'categori':84 'caught':833 'central':279 'chain':526,545 'chang':743 'check':547,1185 'checklist':72,129 'children':805 'circuit':12,52,105,995,1049,1343,1345 'circuitbreak':999,1092 'class':141,165,184,349,373,393,799,998 'close':1008,1013,1061 'code':153,303,314,336,357,367,1235 'common':1290 'complet':751 'componentdidcatch':824 'componentstack':837 'config':774 'configur':110 'console.log':582,1315 'const':605,662,672,698,712,915,950,983,1054,1089,1095,1176 'constructor':145,169,188,1014 'context':222,235,531 'continu':772 'copi':70 'correct':233,426,527,546,597,1263 'correl':643,649,677,685,694,1361,1364 'correlationid':666,673,687,689,703,705,723 'could':1196,1212 'creat':585,624,638 'credit':785 'crypto':656 'currenc':631 'current':65 'custom':138,346,472 'dashboard':850 'data':207,226,242,419,434,505,863,984,1137 'data.id':262 'databas':451,1273 'databaseerror':447 'date':590 'date.now':1034,1068 'db':775,1287 'debug':737 'def':352,376,396 'default':778 'defin':81,116,468 'degrad':16,794,857,860 'delay':951,965,972 'delet':1141 'design':19 'detail':730,1248,1269,1358 'dev':735 'dev/staging':744 'diagnost':738 'dict':400 'drop':510 'dsn':1121,1123 'e':209,228,230,438,449,465,491 'e.errors':444 'e.field':500 'e.message':501 'econnreset':994 'els':1041 'email':1149 'empti':1298 'entry/exit':741 'env':753,1126,1129 'environ':1124 'err':288,297,517,533,542,552,565,992 'err.code':304,315 'err.error':523 'err.message':317,327 'err.message.includes':993 'err.stack':329 'err.statuscode':306,311 'errnotfound':475,553 'error':2,5,20,28,34,39,50,58,67,76,82,90,111,120,130,139,144,156,190,199,202,244,246,253,260,276,280,289,302,313,319,325,326,335,338,342,360,399,405,411,443,452,470,493,504,508,514,525,529,548,762,790,796,809,810,814,818,819,823,825,826,831,834,835,879,887,911,912,936,941,945,947,949,975,982,1048,1065,1079,1109,1152,1166,1170,1183,1221,1231,1234,1244,1254,1276,1288,1337,1341,1372,1383 'error-handl':1 'error.code':1236,1240 'error.errors':254 'error.message':836,888,1277 'error.stack':1262,1279 'errorboundari':800,848,852 'errors.as':564 'errors.is':551 'errors.new':476,481 'errunauthor':480 'event':622,636,716,1134,1145 'event.request':1139 'event.request.headers':1142 'exc':455 'except':347,351,415,420,428,435,446,766,1309,1314 'execut':1024 'exist':1260 'exponenti':895,1330 'expos':1246,1350 'express':274 'extend':143,167,186,801 'extern':1348 'extra':442,1158 'extrem':729 'f':385 'face':119,1163 'fail':196,256,273,409,441,461,463,521,764,1210,1275 'failur':1001,1085 'fallback':760,803,849,853,885,1027,1043,1045,1075,1077 'fals':813 'fatal':769 'fetch':987 'field':486,1326 'filter':594 'fmt.errorf':520,536 'fmt.sprintf':496 'fn':901,934,1025,1057 'forev':214 'format':576 'formatt':612 'found':180,183,389,391,479,557,1192,1199 'friend':1174 'full':787,1268 'func':490 'function':696,740,869,899,1229 'generic':1264,1355 'getcachedrecommend':890 'getdefaultrecommend':892 'getderivedstatefromerror':817 'getlogg':697,714 'getproductrecommend':870 'giant':1369 'global':275 'go':466,467 'grace':15,793,859 'granular':1371 'guid':727 'half':1011,1039 'half-open':1010,1038 'handl':3,6,21,40,59,68,77,91,131,236,749,1303,1373 'handler':277,281,709 'haserror':807,812,821 'header':1140 'hide':213 'hierarchi':140,348 'hook':661 'http.error':554,567 'http.statusbadrequest':570 'http.statusnotfound':558 'id':172,177,178,381,387,644,650,678,686,695,1147,1362,1365 'ignor':503 'implement':4,25,89 'import':601,653,657,1115 'imposs':591 'includ':693,722 'independ':847,1388 'info':456,611,635,739,745,779,827 'info.componentstack':838 'init':353,371,377,384,397,407 'input':1187 'insid':1377 'instanceof':247,298 'instead':1297 'int':362 'integr':1111 'intern':155,337,359,1165,1169,1220,1243,1247 'involv':62 'isoper':158 'iter':732 'javascript':135 'jitter':1333 'job':750 'json':252,312,334,574,599,1253,1283 'json.marshal':506 'keyboardinterrupt':423 'label':614,616 'languag':134 'lastfailur':1004 'later':1228 'layer':93 'let':925 'level':608,610,613,615,634,726 'limit':1201 'list':402 'load':44 'log':9,24,36,55,99,430,573,575,581,600,713,725,781,1271,1301,1322,1359,1376,1380 'log.info':715 'logger':606,691,1319 'logger.child':702 'logger.error':255,323,450,829,1272 'logger.info':621 'logger.warn':300,880,959 'logger.warning':439 'logic':49 'loop':731,1379 'lose':524 'mani':1203 'map':1168 'math.min':952 'math.random':956 'maxdelay':908,920,958 'maxretri':904,916,929,939 'messag':121,146,162,316,339,355,365,372,488,1103,1175,1178,1237,1239,1242,1265,1357 'method':1219 'middlewar':282,646 'miss':773 'moment':1208 'must':283 'never':780 'new':264,589,664,967,974,1047,1091,1285 'next':294,671,690 'nextfunct':295 'nil':518,534 'normal':746 'notfounderror':166,374 'noth':210 'number':150,905,907,909,1017,1021 'observ':41,61 'occur':343 'one':1368 'open':1009,1012,1032,1040,1052,1073,1082 'oper':301,747,763,961,1375 'option':903,923 'order':586,623,637 'orderid':587,627,641,1159 'output':633,721 'param':286 'pars':593 'pass':425 'password':619,782 'passwords/tokens':1323 'path':307,330 'pattern':7,47,107,128,132,894,1293 'payment':717,1104,1155,1209,1211 'paymentcircuit':1090 'paymentcircuit.execute':1098 'paymentservice.charge':1099 'per':1374 'pii':784 'pino':602,604,607,1320 'pleas':1184,1205,1216,1225 'pointless':231 'preserv':544 'privat':1000,1003,1006,1015,1019 'process':418,433,454,460,462,718,1107,1215 'process.env.log':609 'process.env.node':1125,1128 'process.env.sentry':1122 'product':777,1130,1317 'progress':75,78 'promis':902,914,968,1026,1029 'propag':238,648,1363 'proper':429 'provid':1156 'public':148,152,157,189 'python':344,345,1311 'queri':1274,1280 'queryfailederror':1255 'queu':1101 'r':969,971 'rais':445,458 'randomuuid':654,681 'rate':1200 're':219,1306 're-throw':218,1305 'react':795,830,1386 'react.component':802 'react.errorinfo':828 'react.reactnode':804,806 'recommend':881 'recommendationservice.get':876 'record':191,1179 'recover':757 'redact':617,1324 'relat':1256 'render':839 'req':290,669 'req.headers':674 'req.headers.authorization':618 'req.path':308,331 'request':291,652,748,788,1194,1204 'res':292,670 'res.setheader':682 'res.status':250,310,332,1251,1281 'reset':1086 'resettimeout':1020 'resourc':170,175,379,386,477,1195 'respons':51,293 'result':417,432,1055,1063,1096 'retri':10,26,48,103,758,893,960,978,1327,1334,1339 'retryon':910,922,943,944,991 'return':249,309,495,513,519,535,559,571,701,820,840,874,889,932,1044,1062,1076,1144,1233 'save':258,268,272,537 'saveus':206,225,241 'scrub':1135 'section':846,1389 'self':354,378,398 'self.code':366 'self.errors':404 'self.message':364 'self.status':368 'sensit':1136,1325 'sentinel':469 'sentri':1112,1117 'sentry.captureexception':1151 'sentry.init':1120 'sentry.setuser':1146 'sentry/node':1119 'separ':1390 'serv':861 'servic':113,711,767,856,865,882,1367 'set':22,96 'settimeout':970 'setup':1113 'sever':86 'short':1108 'sidebar':854 'silent':203,509 'skill' 'skill-error-handling' 'skip':56 'someth':1222 'source-cloudai-x' 'specif':427,1313 'ssn':620 'stack':328,1261,1278,1351 'stale':862 'state':742,811,1007 'static':816 'status':361,369 'statuscod':149,305 'step':79,87,94,100,108,114,122 'store':699,704 'str':356,358,380,382,401,403 'strategi':11 'string':147,154,171,173,192,193,487,489,494,515,580,667,680,872,1180,1181 'stripe':1157 'struct':485 'structur':8,54,98,572,598,1318 'subsystem':1154 'succeed':759 'summari':1294 'summaries/aggregates':1381 'super':161,174,194,370,383,406 'swallow':201 'systemexit':422 'tag':1153 'task':66 'taxonomi':83 'this.constructor.name':164 'this.failures':1058,1066,1070 'this.lastfailure':1035,1067 'this.name':163 'this.props.children':843 'this.props.fallback':842 'this.resettimeout':1036 'this.state':1031,1037,1060,1072 'this.state.haserror':841 'this.threshold':1071 'threshold':1016 'throw':220,229,263,940,948,973,1046,1078,1307 'tight':1378 'token':783 'topic-agent-skills' 'topic-ai-agents' 'topic-claude-code' 'topic-codex' 'topic-cursor' 'topic-skills' 'topic-workflow' 'touserrespons':1230,1284 'trace':728,1352 'tracessampler':1127 'track':29,74,112,1110 'transient':981 'transient/network':1340 'tri':204,223,239,416,431,873,931,1053,1189,1217,1226 'trigger':45 'trip':1081 'true':160,457,822,1102 'try/catch':46,232,1370 'tsx':798 'type':473,483,549 'typescript':136,137,278,577,645,858,897,997,1114,1167 'unabl':266 'unauthor':482 'unavail':851,855,883 'undefin':815 'unexpect':318,324,341,755 'unhandl':765 'unreach':776,976 'unstructur':579 'usag':706,844,977,1080 'usd':632 'use':17,761,884 'user':118,259,269,271,507,538,583,1162,1173,1177,1238,1241,1250,1257,1267,1354,1356 'user-fac':117,1161 'user-friend':1172 'user.email':1150 'user.id':541,1148 'userid':261,584,625,639,871,877,886,891 'valerr':561,566 'valerr.error':569 'valid':124,195,198,408,410,440,497,1182 'validationerror':185,248,394,436,484,492,562 'valu':734 'var':474,560 'variabl':733 'vs':1164 'w':540,543,555,568 'wait':1206 'warn':754 'went':1223 'winston':1321 'without':221,1328 'withretri':900,986 'workflow':69 'wrap':528,845,1387 'wrong':200,215,413,502,511,578,1224,1245 'x':676,684 'x-correlation-id':675,683","prices":[{"id":"6eacc53b-3545-4083-8cee-a93a8d2e4b35","listingId":"9305e1f2-2caa-4dad-94bd-926c238ad18a","amountUsd":"0","unit":"free","nativeCurrency":null,"nativeAmount":null,"chain":null,"payTo":null,"paymentMethod":"skill-free","isPrimary":true,"details":{"org":"CloudAI-X","category":"claude-workflow-v2","install_from":"skills.sh"},"createdAt":"2026-04-18T21:54:56.451Z"}],"sources":[{"listingId":"9305e1f2-2caa-4dad-94bd-926c238ad18a","source":"github","sourceId":"CloudAI-X/claude-workflow-v2/error-handling","sourceUrl":"https://github.com/CloudAI-X/claude-workflow-v2/tree/main/skills/error-handling","isPrimary":false,"firstSeenAt":"2026-04-18T21:54:56.451Z","lastSeenAt":"2026-05-03T00:52:55.946Z"}],"details":{"listingId":"9305e1f2-2caa-4dad-94bd-926c238ad18a","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"CloudAI-X","slug":"error-handling","github":{"repo":"CloudAI-X/claude-workflow-v2","stars":1352,"topics":["agent-skills","ai","ai-agents","claude-code","codex","cursor","skills","workflow"],"license":"mit","html_url":"https://github.com/CloudAI-X/claude-workflow-v2","pushed_at":"2026-02-14T18:09:29Z","description":"Universal Claude Code workflow plugin with agents, skills, hooks, and commands","skill_md_sha":"cb0f7698471d37c2890ed2d29742061f4e3b0376","skill_md_path":"skills/error-handling/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/CloudAI-X/claude-workflow-v2/tree/main/skills/error-handling"},"layout":"multi","source":"github","category":"claude-workflow-v2","frontmatter":{"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."},"skills_sh_url":"https://skills.sh/CloudAI-X/claude-workflow-v2/error-handling"},"updatedAt":"2026-05-03T00:52:55.946Z"}}