JuliusBrussee/caveman · error · Error

cave_vercel_usage_missing

cave_vercel_usage_missing

Error message

cave_vercel_usage_missing

What it means

`usageFromAISDK` normalizes the AI SDK's `LanguageModelUsage.v4` shape and throws `cave_vercel_usage_missing` when the raw usage is not a record, when `usage.inputTokenDetails` or `usage.outputTokenDetails` are missing/not records, when `usage.inputTokens` is not a non-negative safe integer, when the cache fields inside `inputTokenDetails` are not integers — or (line 384) when `cacheReadTokens + cacheWriteTokens` already exceeds the reported total `inputTokens`. The adapter demands complete token accounting because usage feeds priced evidence.

Solutions

  1. Run a raw `agent.generate` and assert the response carries `usage.inputTokens` plus both `*TokenDetails` records with integer values
  2. Pin `ai@7.0.43` and use a provider implementation that emits v4 usage details
  3. Remove or fix middleware that mutates/strips `response.usage`
  4. If cache fields exceed input, capture the raw usage object and report it to the provider package — do not guess which number is right
Defensive patterns

Strategy: validation

Validate before calling

// pre-flight: assert the provider emits LanguageModelUsage.v4 with all fields
const { usage } = await agent.generate({ prompt: 'ping' }) as { usage: any };
const ok = usage && Number.isSafeInteger(usage.inputTokens) &&
  usage.inputTokenDetails && usage.outputTokenDetails &&
  (!usage.inputTokenDetails.cacheReadTokens ||
   usage.inputTokenDetails.cacheReadTokens + (usage.inputTokenDetails.cacheWriteTokens ?? 0) <= usage.inputTokens);
if (!ok) throw new Error('provider does not emit complete v4 usage details');

Type guard

function hasV4Usage(u: unknown): boolean {
  if (typeof u !== 'object' || u === null) return false;
  const s = u as Record<string, any>;
  return Number.isSafeInteger(s.inputTokens) &&
    typeof s.inputTokenDetails === 'object' && s.inputTokenDetails !== null &&
    typeof s.outputTokenDetails === 'object' && s.outputTokenDetails !== null;
}

Prevention

When it happens

Trigger: A provider integration that omits `inputTokenDetails`/`outputTokenDetails` entirely; `usage.inputTokens` missing on an error-adjacent path; a provider reporting `cacheReadTokens` greater than its own `inputTokens`.

Common situations: Community AI SDK providers that never emit v4 usage details; a different `ai` package version with a changed usage shape (the adapter pins 7.0.43 exactly); middleware (caching, tracing) stripping or replacing `response.usage`.

Related errors


AI-assisted analysis of JuliusBrussee/caveman@766dce6b13 (2026-08-18). Data as JSON: /api/errors/42cfe918c4bcb32e. Report an issue: GitHub.

Appendix: source

Thrown at packages/agent/src/adapters.ts:384

    ...input.usage,
    costUsd: priced.catalogCostUsd,
    usageBasis: "provider_reported",
    priceBasis: "public_catalog",
    evaluatedTransformIDs: [...input.request.evaluatedTransformIDs],
    appliedTransformIDs: [...input.request.appliedTransformIDs],
    recoveryResolved: input.request.recoveryResolved,
    latencyMs: input.latencyMs,
  };
}

function usageFromAISDK(value: unknown, reasoningRequired: boolean): NormalizedUsage {
  const usage = record(value, "cave_vercel_usage_missing");
  const input = record(usage.inputTokenDetails, "cave_vercel_usage_missing");
  const output = record(usage.outputTokenDetails, "cave_vercel_usage_missing");
  const totalInput = strictInteger(usage.inputTokens, "cave_vercel_usage_missing");
  const cacheRead = optionalInteger(input.cacheReadTokens, "cave_vercel_usage_missing");
  const cacheWrite = optionalInteger(input.cacheWriteTokens, "cave_vercel_usage_missing");
  if (cacheRead + cacheWrite > totalInput) throw new Error("cave_vercel_usage_missing");
  const noCache = input.noCacheTokens === undefined
    ? totalInput - cacheRead - cacheWrite
    : strictInteger(input.noCacheTokens, "cave_vercel_usage_missing");
  if (noCache + cacheRead + cacheWrite !== totalInput) {
    throw new Error("cave_vercel_usage_missing");
  }
  const normalized = normalizeUsage({
    inputTokens: noCache,
    outputTokens: usage.outputTokens,
    cacheReadTokens: cacheRead,
    cacheWriteTokens: cacheWrite,
    reasoningTokens: output.reasoningTokens,
    totalTokens: usage.totalTokens,
  }, reasoningRequired, "cave_vercel_usage_missing");
  return normalized;
}

function usageFromMastra(value: unknown, reasoningRequired: boolean): NormalizedUsage {

View on GitHub (pinned to 766dce6b13)