{"record":{"id":"aefd5524e00afdc6","repo":"JuliusBrussee/caveman","slug":"cave-provider-identity-missing","errorCode":"cave_provider_identity_missing","errorMessage":"cave_provider_identity_missing","messagePattern":"cave_provider_identity_missing","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/agent/src/execution-kernel.ts","lineNumber":131,"sourceCode":"  totalTokens: number;\n}\n\nexport interface ValidatedProviderUsage extends ProviderUsageEvidence {\n  priced: boolean;\n  catalogCostUsd: number;\n}\n\nexport function validateProviderUsage(\n  evidence: ProviderUsageEvidence,\n  options: {\n    expected?: { provider: string; model: string };\n    reportedCostUsd?: number;\n    requirePriced?: boolean;\n  } = {},\n): ValidatedProviderUsage {\n  if (typeof evidence.provider !== \"string\" || evidence.provider.length === 0 ||\n      typeof evidence.model !== \"string\" || evidence.model.length === 0) {\n    throw new Error(\"cave_provider_identity_missing\");\n  }\n  if (options.expected !== undefined &&\n      (evidence.provider !== options.expected.provider || evidence.model !== options.expected.model)) {\n    throw new Error(\"cave_provider_model_identity_mismatch\");\n  }\n  const values = [\n    evidence.inputTokens,\n    evidence.outputTokens,\n    evidence.cacheReadTokens,\n    evidence.cacheWriteTokens,\n    evidence.reasoningTokens,\n    evidence.totalTokens,\n  ];\n  const disjointTotal = evidence.inputTokens + evidence.outputTokens +\n    evidence.cacheReadTokens + evidence.cacheWriteTokens;\n  if (values.some((value) => !Number.isSafeInteger(value) || value < 0) ||\n      evidence.totalTokens <= 0 || evidence.totalTokens !== disjointTotal ||\n      evidence.reasoningTokens > evidence.outputTokens) {","sourceCodeStart":113,"sourceCodeEnd":149,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/3ee70a102609e550bd2e68004bf5990a9341c851/packages/agent/src/execution-kernel.ts#L113-L149","documentation":"validateProviderUsage requires usage evidence to identify which provider and model produced it. It throws when evidence.provider or evidence.model is missing, not a string, or an empty string, because cost/usage validation is meaningless without provider identity. It runs before any pricing or expectation checks.","triggerScenarios":"Calling priced, validateExecution, or usage with evidence lacking provider/model — e.g. an upstream response where provider fields were dropped, or a caller passing a partial usage record.","commonSituations":"A provider adapter that forgets to populate provider/model on usage; streaming responses where the usage chunk arrives without identity metadata; aggregating usage across providers and dropping identity fields; passing a raw token-count object instead of the evidence shape.","solutions":["Populate evidence.provider and evidence.model before validating usage.","Fix or update the provider adapter so it emits provider/model identity on usage evidence.","If aggregating, carry provider/model through merge/reduce steps.","Check that you are passing the library's evidence object, not a hand-built partial object missing required fields."],"exampleFix":"// before\nvalidateProviderUsage({ inputTokens: 10, outputTokens: 5 });\n// after\nvalidateProviderUsage({ provider: \"anthropic\", model: \"claude-sonnet-4\", inputTokens: 10, outputTokens: 5 });","handlingStrategy":"validation","validationCode":"function hasProviderIdentity(evidence: { provider?: unknown; model?: unknown }): boolean {\n  return typeof evidence.provider === \"string\" && evidence.provider.length > 0 &&\n         typeof evidence.model === \"string\" && evidence.model.length > 0;\n}\nif (!hasProviderIdentity(evidence)) throw new Error(\"usage evidence missing provider/model\");","typeGuard":"function hasProviderIdentity(e: { provider?: unknown; model?: unknown }): e is { provider: string; model: string } {\n  return typeof e.provider === \"string\" && e.provider.length > 0 && typeof e.model === \"string\" && e.model.length > 0;\n}","tryCatchPattern":"try {\n  const usage = validateProviderUsage(evidence, { expected });\n} catch (err) {\n  if (err instanceof Error && err.message === \"cave_provider_identity_missing\") {\n    throw new Error(\"provider adapter returned usage without provider/model identity — fix the adapter or pass a complete evidence object\");\n  }\n  throw err;\n}","preventionTips":["Always populate provider and model when constructing usage evidence.","Type usage records so provider/model are required fields, not optional.","When merging usage across chunks/providers, carry identity fields through.","Add an adapter-level test asserting usage output includes provider and model."],"tags":["execution-kernel","usage","validation","missing-field"],"backgroundTag":"missing-required-argument","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"}