{"record":{"id":"fdf08fad275cff2d","repo":"can1357/oh-my-pi","slug":"failuremessage-recoveryhint-subagent-failure","errorCode":null,"errorMessage":"${failureMessage}${recoveryHint} (subagent failure: ${policy.agentName} exited ${result.exitCode} or errored/aborted)","messagePattern":"(.+?)(.+?) \\(subagent failure: (.+?) exited (.+?) or errored/aborted\\)","errorType":"exception","errorClass":"ToolError","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/eval/agent-bridge.ts","lineNumber":173,"sourceCode":"\t\t\t\t\tkeepAlive: false,\n\t\t\t\t\t// `maxRuntimeMs` is intentionally omitted: the executor then inherits\n\t\t\t\t\t// `task.maxRuntimeMs`, matching the task tool. Pinning it to 0 here\n\t\t\t\t\t// silently overrode the user's wall-clock cap for eval fan-outs.\n\t\t\t\t\tshareEvalSession: false,\n\t\t\t\t\t...(options.signal !== undefined ? { signal: options.signal } : {}),\n\t\t\t\t\t...(options.emitStatus\n\t\t\t\t\t\t? { onProgress: (progress: AgentProgress) => emitProgressStatus(options.emitStatus, progress) }\n\t\t\t\t\t\t: {}),\n\t\t\t\t}),\n\t\t\t{ deferExternalAbort: true },\n\t\t);\n\t\tconst { result, policy, mergeSummary, changesApplied, artifactsDir } = execution;\n\t\tif (result.exitCode !== 0 || result.error || result.aborted) {\n\t\t\tconst failureMessage = buildSubagentFailureMessage(policy.agentName, result)\n\t\t\t\t.replace(/<\\/?system-notification>/g, \"\")\n\t\t\t\t.trim();\n\t\t\tconst recoveryHint = policy.isIsolated ? await buildStructuredSubagentRecoveryHint(result, artifactsDir) : \"\";\n\t\t\tthrow new ToolError(`${failureMessage}${recoveryHint}`);\n\t\t}\n\t\tif (policy.isIsolated && changesApplied === false) {\n\t\t\tconst summary = mergeSummary.replace(/<\\/?system-notification>/g, \"\").trim();\n\t\t\tconst recoveryHint = await buildStructuredSubagentRecoveryHint(result, artifactsDir);\n\t\t\tthrow new ToolError(\n\t\t\t\t`agent() isolated apply failed for ${result.id}${summary ? `: ${summary}` : \"\"}${recoveryHint}`,\n\t\t\t);\n\t\t}\n\n\t\tconst structuredOutput = result.structuredOutput;\n\t\tconst structured = structuredOutput?.source !== undefined && structuredOutput.source !== \"none\";\n\t\tif (structured && mergeSummary.includes(\"<system-notification>\")) {\n\t\t\tconst recoveryHint = await buildStructuredSubagentRecoveryHint(result, artifactsDir);\n\t\t\tthrow new ToolError(\n\t\t\t\t`agent() isolated nested patch apply failed for ${result.id}: ${mergeSummary.replace(/<\\/?system-notification>/g, \"\").trim()}${recoveryHint}`,\n\t\t\t);\n\t\t}\n","sourceCodeStart":155,"sourceCodeEnd":191,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/eval/agent-bridge.ts#L155-L191","documentation":"When the spawned eval subagent exits non-zero, errors, or aborts, the bridge surfaces buildSubagentFailureMessage (tag-stripped) plus — for isolated subagents — a structured recovery hint, wrapped in a ToolError. It means the delegated agent() run itself failed, not the parent tool.","triggerScenarios":"agent() call where the subagent process returned exitCode !== 0, set result.error, or was aborted (result.aborted) — crash, OOM, model/API failure, user abort, or unhandled exception inside the subagent.","commonSituations":"Subagent hit an API rate limit or auth failure; prompt caused the subagent to exceed its own limits and abort; environment missing a binary the subagent invoked; eval infrastructure killed the process.","solutions":["Read failureMessage for the subagent's own error and the recovery hint for artifacts location","Re-run with a smaller/simpler prompt to isolate the failure","Check subagent logs/artifacts dir for the underlying stack trace","Fix auth/network/model-availability issues indicated in the message"],"exampleFix":"// before: prompt causes subagent crash, no diagnosis\nagent({ prompt: hugePrompt })\n// after: inspect artifacts and retry with constrained prompt\ntry { await agent({ prompt }) } catch (e) { console.log(e.message /* includes artifactsDir hint */) }","handlingStrategy":"try-catch","validationCode":"// pre-check environment the subagent needs\nif (!(await $which('git'))) throw new Error('subagent requires git on PATH');","typeGuard":"function subagentFailed(r: { exitCode: number; error?: unknown; aborted?: boolean }): boolean { return r.exitCode !== 0 || !!r.error || r.aborted; }","tryCatchPattern":"try { await agent(args) } catch (e) { const m = e.message; if (/subagent failure/.test(m)) { inspectArtifacts(m); retryWithSmallerPrompt(); } else throw e }","preventionTips":["Keep subagent prompts scoped so they finish within limits","Verify API keys/model availability before eval runs","Avoid aborting the parent mid-subagent","Check artifacts dir from the recovery hint on any failure"],"tags":["subagent","eval","process-exit","aborted"],"backgroundTag":"subagent-exited-nonzero","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}