JuliusBrussee/caveman · error

cave_provider_identity_missing

cave_provider_identity_missing

Error message

cave_provider_identity_missing

What it means

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.

Solutions

  1. Populate evidence.provider and evidence.model before validating usage.
  2. Fix or update the provider adapter so it emits provider/model identity on usage evidence.
  3. If aggregating, carry provider/model through merge/reduce steps.
  4. Check that you are passing the library's evidence object, not a hand-built partial object missing required fields.

Example fix

// before
validateProviderUsage({ inputTokens: 10, outputTokens: 5 });
// after
validateProviderUsage({ provider: "anthropic", model: "claude-sonnet-4", inputTokens: 10, outputTokens: 5 });
Defensive patterns

Strategy: validation

Validate before calling

function hasProviderIdentity(evidence: { provider?: unknown; model?: unknown }): boolean {
  return typeof evidence.provider === "string" && evidence.provider.length > 0 &&
         typeof evidence.model === "string" && evidence.model.length > 0;
}
if (!hasProviderIdentity(evidence)) throw new Error("usage evidence missing provider/model");

Type guard

function hasProviderIdentity(e: { provider?: unknown; model?: unknown }): e is { provider: string; model: string } {
  return typeof e.provider === "string" && e.provider.length > 0 && typeof e.model === "string" && e.model.length > 0;
}

Try / catch

try {
  const usage = validateProviderUsage(evidence, { expected });
} catch (err) {
  if (err instanceof Error && err.message === "cave_provider_identity_missing") {
    throw new Error("provider adapter returned usage without provider/model identity — fix the adapter or pass a complete evidence object");
  }
  throw err;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20). Data as JSON: /api/errors/aefd5524e00afdc6. Report an issue: GitHub.

Appendix: source

Thrown at packages/agent/src/execution-kernel.ts:131

  totalTokens: number;
}

export interface ValidatedProviderUsage extends ProviderUsageEvidence {
  priced: boolean;
  catalogCostUsd: number;
}

export function validateProviderUsage(
  evidence: ProviderUsageEvidence,
  options: {
    expected?: { provider: string; model: string };
    reportedCostUsd?: number;
    requirePriced?: boolean;
  } = {},
): ValidatedProviderUsage {
  if (typeof evidence.provider !== "string" || evidence.provider.length === 0 ||
      typeof evidence.model !== "string" || evidence.model.length === 0) {
    throw new Error("cave_provider_identity_missing");
  }
  if (options.expected !== undefined &&
      (evidence.provider !== options.expected.provider || evidence.model !== options.expected.model)) {
    throw new Error("cave_provider_model_identity_mismatch");
  }
  const values = [
    evidence.inputTokens,
    evidence.outputTokens,
    evidence.cacheReadTokens,
    evidence.cacheWriteTokens,
    evidence.reasoningTokens,
    evidence.totalTokens,
  ];
  const disjointTotal = evidence.inputTokens + evidence.outputTokens +
    evidence.cacheReadTokens + evidence.cacheWriteTokens;
  if (values.some((value) => !Number.isSafeInteger(value) || value < 0) ||
      evidence.totalTokens <= 0 || evidence.totalTokens !== disjointTotal ||
      evidence.reasoningTokens > evidence.outputTokens) {

View on GitHub (pinned to 3ee70a1026)