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
- Run a raw `agent.generate` and assert the response carries `usage.inputTokens` plus both `*TokenDetails` records with integer values
- Pin `ai@7.0.43` and use a provider implementation that emits v4 usage details
- Remove or fix middleware that mutates/strips `response.usage`
- 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
- Smoke-test one raw generate and assert usage shape before adopting a provider
- Pin ai@7.0.43 exactly — other versions change the usage contract
- Don't let middleware rewrite or strip response.usage
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
- cave_mastra_usage_missing
- cave_eve_usage_missing
- cave_vercel_terminal_failure
- cave_eve_terminal_${result.status}
- cave_harness_incomplete_evidence
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)