JuliusBrussee/caveman · error · Error
cave_provider_model_identity_mismatch
cave_provider_model_identity_mismatch
Error message
cave_provider_model_identity_mismatch
What it means
Thrown by validateProviderUsage (packages/agent/src/execution-kernel.ts:135): the evidence's provider/model pair does not match the expected pair passed in options.expected. The framework enforces that the model that actually answered is exactly the model that was selected in the plan — no silent substitution by the provider.
Source
Thrown at packages/agent/src/execution-kernel.ts:135
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) {
throw new Error("cave_provider_usage_incomplete");
}
const priced = catalogCost({
provider: evidence.provider,View on GitHub (pinned to 27d5a3981a)
Solutions
- Compare evidence.model with expected.model strings to see the exact substitution; if the provider legitimately returns a concrete id for your alias, configure the plan with the exact id the provider reports.
- Regenerate the lock/plan after changing the model so expected identity matches what the provider reports.
- If a proxy rewrites model names, make it pass the original model string through, or align the configured model with what arrives.
Example fix
// before
validateProviderUsage(evidence, { expected: { provider: "anthropic", model: "claude-sonnet-4-5" } });
// evidence.model === "claude-sonnet-4-20250514"
// after
// configure the plan with the concrete id the provider reports
agent({ model: "anthropic/claude-sonnet-4-20250514", /* ... */ }); Defensive patterns
Strategy: validation
Validate before calling
function identityMatches(evidence: { provider: string; model: string }, expected: { provider: string; model: string }): boolean {
return evidence.provider === expected.provider && evidence.model === expected.model;
}
if (expected && !identityMatches(evidence, expected)) {
console.error(`model substitution: expected ${expected.model}, got ${evidence.model}`);
} Prevention
- Configure plans with the exact concrete model id the provider reports, not aliases.
- Log evidence.model on every reserved turn to catch substitution early.
- After provider model migrations, regenerate locks so expected identity matches.
When it happens
Trigger: Calling validateProviderUsage with options.expected set (as locked runs and reserved turns do) while the reported evidence names a different provider or model string (e.g. expected 'anthropic/claude-sonnet-4-5' but the API reported 'claude-sonnet-4-20250514' or a different deployment).
Common situations: Provider aliasing: requesting a model alias and receiving the concrete dated model id back; a gateway/proxy rewriting model names; stale plan/lock expecting an old model id after a provider migration; mismatched casing or whitespace in model strings.
Related errors
- cave_provider_identity_missing
- cave_provider_usage_incomplete
- unsupported provider ${JSON.stringify(value)}
- option not found
- cave_harness_adapter_version_invalid
AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15).
Data as JSON: /api/errors/e98cfd76466a8616.
Report an issue: GitHub.