{"record":{"id":"129e89ede7c4bf9f","repo":"coleam00/Archon","slug":"claude-api-error-sdkerrorcode-resulttext","errorCode":null,"errorMessage":"Claude API error (${sdkErrorCode}): ${resultText}","messagePattern":"Claude API error \\((.+?)\\): (.+?)","errorType":"exception","errorClass":"ClaudeApiResultError","httpStatus":null,"severity":"error","filePath":"packages/providers/src/claude/provider.ts","lineNumber":1203,"sourceCode":"        (syntheticError !== undefined || resultMsg.terminal_reason === 'api_error')\n      ) {\n        const code = syntheticError?.code ?? 'unknown';\n        const text =\n          syntheticError?.text ||\n          resultMsg.result ||\n          sdkErrors?.join('; ') ||\n          'API error result with no error text';\n        getLog().error(\n          {\n            sessionId: resultMsg.session_id,\n            errorCode: code,\n            terminalReason: resultMsg.terminal_reason,\n            apiErrorStatus: resultMsg.api_error_status,\n            text,\n          },\n          'claude.result_api_error'\n        );\n        throw new ClaudeApiResultError(code, text);\n      }\n\n      // Fail-safe (never observed in practice): a synthetic error message\n      // followed by a non-error result. Yield the withheld text late rather\n      // than silently swallowing content.\n      if (syntheticError !== undefined && !resultMsg.is_error) {\n        getLog().warn(\n          { sessionId: resultMsg.session_id, errorCode: syntheticError.code },\n          'claude.synthetic_error_not_confirmed'\n        );\n        yield { type: 'assistant', content: syntheticError.text };\n      }\n\n      // SDKResultSuccess declares `is_error: boolean` (not literal false). When a\n      // model terminates via a configured stop sequence (stop_reason ===\n      // 'stop_sequence') the SDK can set is_error: true while keeping\n      // subtype: 'success' — its encoding of \"non-default termination, not a\n      // failure\". Treat that pair as a clean success so downstream consumers","sourceCodeStart":1185,"sourceCodeEnd":1221,"githubUrl":"https://github.com/coleam00/Archon/blob/0773b9745896ef0612e709c80845a0f7db315b19/packages/providers/src/claude/provider.ts#L1185-L1221","documentation":"streamClaudeMessages throws ClaudeApiResultError when the Claude Agent SDK stream ends with a result message flagged as an API error. The message embeds the SDK's error code (sdkErrorCode from the result message, plus api_error_status and terminal_reason logged under 'claude.result_api_error') followed by the accumulated result text, so callers can classify retryability from the code.","triggerScenarios":"The Claude API returns an error result for the query: rate limiting (429), API overload (529/5xx), invalid API key or expired subscription auth, prompt flagged by safety filters, or request/context limits exceeded — surfaced by the SDK as an is_error result message rather than a thrown exception.","commonSituations":"Hitting rate limits during parallel agent fan-out; Anthropic API incident or outage; expired OAuth session for a Claude subscription; model id not accessible to the account; oversized context from a huge repo snapshot.","solutions":["Read the sdkErrorCode embedded in the message to classify: rate-limit/overloaded → retry with backoff; authentication → re-authenticate the Claude SDK (fresh `claude login` / valid API key).","Check apiErrorStatus and terminalReason in the 'claude.result_api_error' log for retryability.","For rate limits, reduce parallelism or add exponential backoff before retrying sendQuery.","Verify the configured model is available to the account and the prompt/context size is within limits."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// before invoking the provider\nconst key = process.env.ANTHROPIC_API_KEY;\nif (!key) {\n  throw new Error('ANTHROPIC_API_KEY missing; fix auth before querying Claude');\n}","typeGuard":"class ClaudeApiResultError extends Error {\n  constructor(public code: string, public resultText: string) {\n    super(`Claude API error (${code}): ${resultText}`);\n  }\n}\nfunction isClaudeApiResultError(e: unknown): e is ClaudeApiResultError {\n  return e instanceof ClaudeApiResultError;\n}","tryCatchPattern":"try {\n  await provider.sendQuery(req);\n} catch (err) {\n  if (isClaudeApiResultError(err) && /rate|overload|429|529/i.test(err.code)) {\n    await sleep(backoff); // exponential backoff + jitter, then retry\n  } else if (isClaudeApiResultError(err) && /auth|401|403/i.test(err.code)) {\n    throw new Error('Claude authentication failed — re-authenticate the SDK');\n  } else {\n    throw err;\n  }\n}","preventionTips":["Add exponential backoff with jitter on rate-limit/overload error codes.","Keep prompt/context size within model limits before sending.","Monitor provider status and pause parallel fan-out runs during incidents.","Rotate/refresh Claude credentials proactively in long-lived workers."],"tags":["api","claude","rate-limit","network"],"backgroundTag":"api-rate-limit-exceeded","analyzedSha":"0773b9745896ef0612e709c80845a0f7db315b19","analyzedAt":"2026-09-01T02:28:07.064Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}