{"record":{"id":"11a7a1d03a55b7f4","repo":"JuliusBrussee/caveman","slug":"cave-subagent-unpriced-budget","errorCode":"cave_subagent_unpriced_budget","errorMessage":"cave_subagent_unpriced_budget","messagePattern":"cave_subagent_unpriced_budget","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/agent/src/runtime.ts","lineNumber":4666,"sourceCode":"\nfunction reserveProviderSpend(\n  ledgers: readonly SpendLedger[],\n  model: Model<Api>,\n  requestedOutputTokens: number | undefined,\n): SpendReservation[] {\n  if (ledgers.length === 0) return [];\n  const outputTokens = Math.min(\n    model.maxTokens,\n    requestedOutputTokens ?? model.maxTokens,\n  );\n  const ceilingUsd = catalogSearchCeiling(\n    `${model.provider}/${model.id}`,\n    model.contextWindow,\n    outputTokens,\n  );\n  if (ceilingUsd === undefined) {\n    markSpendIncomplete(ledgers);\n    throw new Error(\"cave_subagent_unpriced_budget\");\n  }\n  for (const ledger of ledgers) {\n    if (ledger.incomplete) throw new Error(\"cave_subagent_spend_evidence_incomplete\");\n    if (ledger.actualUsd + ledger.reservedUsd + ceilingUsd > ledger.limitUsd) {\n      throw new Error(ledger.exceededCode);\n    }\n  }\n  const reservations = ledgers.map((ledger) => ({\n    ledger,\n    ceilingUsd,\n    provider: model.provider,\n    model: model.id,\n  }));\n  for (const { ledger } of reservations) ledger.reservedUsd += ceilingUsd;\n  return reservations;\n}\n\nfunction settleProviderSpend(","sourceCodeStart":4648,"sourceCodeEnd":4684,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/3ee70a102609e550bd2e68004bf5990a9341c851/packages/agent/src/runtime.ts#L4648-L4684","documentation":"When preparing a subagent budget reservation, the runtime computes a USD ceiling for the model/context/output combination. If the ceiling cannot be computed because the model has no price (ceilingUsd === undefined), the runtime marks all spend ledgers incomplete — preserving honest accounting — and throws this error rather than reserving an unknown amount.","triggerScenarios":"Invoking the subagent budget-reservation function (runtime.ts:4666) with a model whose catalog pricing lookup returns undefined for the given provider/id, contextWindow, and outputTokens combination.","commonSituations":"Subagent configured with an unpriced custom or preview model; provider string not matching catalog entries (e.g. 'openai' vs 'azure/openai'); outputTokens requested beyond priced tiers so no ceiling formula applies.","solutions":["Use a priced model for the subagent, or correct the provider/model id so it matches the catalog.","Reduce requested outputTokens/contextWindow to a configuration the pricing catalog covers.","Extend the pricing catalog with the model's per-token prices if you maintain it.","Disable cost budgeting for this subagent (no meter/ledger) if unpriced execution is acceptable — noting spend evidence will be marked incomplete."],"exampleFix":"// before\nconst sub = runtime.spawnSubagent({ model: 'anthropic/claude-preview-x' });\n// after: priced, catalog-known model\nconst sub = runtime.spawnSubagent({ model: 'anthropic/claude-sonnet-4' });","handlingStrategy":"validation","validationCode":"const ceilingUsd = priceCeiling(model.provider, model.id, model.contextWindow, outputTokens);\nif (ceilingUsd === undefined) throw new Error('cannot reserve: model unpriced');","typeGuard":"const isPricedForReservation = (model, outputTokens) =>\n  priceCeiling(model.provider, model.id, model.contextWindow, outputTokens) !== undefined;","tryCatchPattern":"try {\n  await reserveBudget({ model, outputTokens, ledgers });\n} catch (e) {\n  if (e.message === 'cave_subagent_unpriced_budget') {\n    switchToPricedModelOrDropBudget();\n  } else throw e;\n}","preventionTips":["Only assign priced models to budgeted subagents.","Confirm provider/id strings match catalog entries exactly.","Check ceiling availability before opening new ledgers."],"tags":["pricing","budget","subagent","catalog"],"backgroundTag":"invalid-config-value","analyzedSha":"3ee70a102609e550bd2e68004bf5990a9341c851","analyzedAt":"2026-09-20T15:53:39.229Z","contentChangedAt":"2026-09-20T15:53:39.229Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}