{"record":{"id":"6f292419e0bfde4e","repo":"coleam00/Archon","slug":"node-node-id-failed-sdk-returned-subtype","errorCode":null,"errorMessage":"Node '${node.id}' failed: SDK returned ${subtype}${errorsDetail}","messagePattern":"Node '(.+?)' failed: SDK returned (.+?)(.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/workflows/src/dag-executor.ts","lineNumber":2653,"sourceCode":"        // clean stop_sequence termination. The Claude provider already filters\n        // this out, but the guard here keeps a third-party IAgentProvider that\n        // forwards the SDK pair raw from producing a \"SDK returned success\"\n        // false failure.\n        if (msg.isError && msg.errorSubtype !== 'success') {\n          const subtype = msg.errorSubtype ?? 'unknown';\n          const errorsDetail = msg.errors?.length ? ` — ${msg.errors.join('; ')}` : '';\n          getLog().error(\n            {\n              nodeId: node.id,\n              errorSubtype: subtype,\n              errors: msg.errors,\n              sessionId: msg.sessionId,\n              stopReason: msg.stopReason,\n              durationMs: Date.now() - nodeStartTime,\n            },\n            'dag.node_sdk_error_result'\n          );\n          throw new Error(`Node '${node.id}' failed: SDK returned ${subtype}${errorsDetail}`);\n        }\n        if (backgroundTasks.shouldBreakOnResult()) {\n          break; // Result is the \"I'm done\" signal — don't wait for subprocess to exit\n        }\n        // Result arrived with background Agent tasks still live (#2083).\n        // Breaking here would .return() the generator chain → SDK cleanup →\n        // SIGTERM the CLI → kill the tasks and lose their pending artifacts.\n        // Keep consuming: the SDK holds the subprocess open until the tasks\n        // drain, runs a follow-up turn to integrate their output, and emits a\n        // final result (whose fields overwrite the captures above — correct,\n        // since SDK cost/usage are session-cumulative). Bounded by the\n        // existing idle timeout; task_progress chunks reset it.\n        getLog().warn(\n          {\n            nodeId: node.id,\n            taskCount: backgroundTasks.count(),\n            taskIds: backgroundTasks.ids(),\n          },","sourceCodeStart":2635,"sourceCodeEnd":2671,"githubUrl":"https://github.com/coleam00/Archon/blob/0773b9745896ef0612e709c80845a0f7db315b19/packages/workflows/src/dag-executor.ts#L2635-L2671","documentation":"Thrown when the model SDK stream delivers an error result message (an isError result with a subtype other than the budget cap, which has its own error). The executor logs dag.node_sdk_error_result and fails the node, including the SDK subtype and any collected error details, because silently breaking out of the stream previously produced empty output disguised as success.","triggerScenarios":"The provider SDK surfaces a terminal error result during a node's agent turn — e.g. api_error, overloaded, invalid_request, authentication failures — and `subtype` names it in the message.","commonSituations":"Provider outages or rate limiting (overloaded_error); expired/invalid API credentials; malformed request rejected by the model API; network interruption mid-turn.","solutions":["Read the `subtype` and errorsDetail in the message to identify the SDK failure cause.","Fix authentication if the subtype indicates auth/permission problems (check API keys/env).","Retry on transient subtypes (overloaded/api_error) — ideally via the node's retry policy.","Check provider status/incidents if errors persist; upgrade the provider SDK if the subtype is unknown to your version."],"exampleFix":"// before\nnode:\n  id: plan\n# after — add retry for transient SDK errors\nnode:\n  id: plan\n  retry:\n    attempts: 3\n    on: [overloaded_error, api_error]","handlingStrategy":"retry","validationCode":"// validate credentials/config before the run\nif (!process.env.ANTHROPIC_API_KEY && !hasStoredCredentials()) throw new Error('No provider credentials configured');","typeGuard":null,"tryCatchPattern":"try {\n  await runNode(node);\n} catch (e) {\n  const m = String(e).match(/SDK returned ([\\w_]+)/);\n  if (m && ['overloaded_error','api_error','rate_limit_error'].includes(m[1])) {\n    await retryWithBackoff(() => runNode(node), { attempts: 3 });\n  } else throw e;\n}","preventionTips":["Configure node-level retry for transient SDK subtypes.","Verify API keys and provider status before long runs.","Keep the provider SDK updated to get accurate subtypes."],"tags":["sdk","provider","agent"],"backgroundTag":"sdk-error-result","analyzedSha":"0773b9745896ef0612e709c80845a0f7db315b19","analyzedAt":"2026-09-01T02:28:07.064Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}