{"record":{"id":"35e6bfa412b99937","repo":"JuliusBrussee/caveman","slug":"cave-provider-terminal-finalmessage-stopreason","errorCode":null,"errorMessage":"cave_provider_terminal_${finalMessage.stopReason}","messagePattern":"cave_provider_terminal_(.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/agent/src/runtime.ts","lineNumber":2111,"sourceCode":"        (efficiencyPlan !== undefined ||\n          executionContext.spendLedgers.length > 0 ||\n          usageFailure.message === \"cave_provider_model_identity_mismatch\" ||\n          usageFailure.message === \"cave_provider_identity_missing\")) {\n      throw usageFailure;\n    }\n    if (pendingSpendReservations.length > 0) {\n      markSpendIncomplete(executionContext.spendLedgers);\n      throw new Error(\"cave_subagent_spend_evidence_incomplete\");\n    }\n    // A run stopped before its first call has no assistant message, and that is\n    // the honest outcome rather than missing evidence: the caller gets an empty\n    // answer, zero usage, and the reason the runtime declined to spend.\n    if (!finalMessage && stopReason === undefined) {\n      throw new Error(\"cave_incomplete_evidence: Pi emitted no final assistant message\");\n    }\n    if (finalMessage &&\n        (finalMessage.stopReason === \"error\" || finalMessage.stopReason === \"aborted\")) {\n      throw new Error(`cave_provider_terminal_${finalMessage.stopReason}`);\n    }\n    const text = finalMessage === undefined ? \"\" : assistantText(finalMessage);\n    if (definition.output?.schema && finalMessage !== undefined) {\n      let parsed: unknown;\n      try {\n        parsed = JSON.parse(text);\n      } catch {\n        throw new Error(\"cave_output_schema_invalid_json\");\n      }\n      if (!Value.Check(definition.output.schema, parsed)) {\n        throw new Error(\"cave_output_schema_mismatch\");\n      }\n    }\n    if (appliedPlan.appliedTransformIDs.length > 0 && !cacheBoundaryKnown) {\n      cacheBust = true;\n      markRequestPassThrough(headers, appliedPlan, \"cache_boundary_unobserved\");\n    }\n    for (const child of nestedReceipts) receipt.recordSubagent(child);","sourceCodeStart":2093,"sourceCodeEnd":2129,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/766dce6b1394ebb56a3090748d5a0240a5aefb36/packages/agent/src/runtime.ts#L2093-L2129","documentation":"Terminal-state guard: the provider run finished with stopReason 'error' or 'aborted', which is surfaced as a typed failure (cave_provider_terminal_error / cave_provider_terminal_aborted) rather than a silent empty answer.","triggerScenarios":"Thrown at packages/agent/src/runtime.ts:2111 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Parse the stop reason after the cave_provider_terminal_ prefix to get the provider cause","Retry on transient provider errors; inspect provider diagnostics otherwise","Check abort signals — an aborted request surfaces here"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"766dce6b1394ebb56a3090748d5a0240a5aefb36","analyzedAt":"2026-08-18T03:14:35.516Z","contentChangedAt":"2026-08-18T03:14:35.516Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}