can1357/oh-my-pi · error · AnthropicStreamEnvelopeError
Anthropic cache refresh response omitted usage
Error message
Anthropic cache refresh response omitted usage
What it means
This AnthropicStreamEnvelopeError is thrown when the cache-refresh response body is a valid JSON object but has no parsable usage field. The whole point of the cache-refresh call is to obtain up-to-date token/cache usage numbers, so a response without usage is useless and the library fails rather than reporting zeros.
Source
Thrown at packages/ai/src/providers/anthropic.ts:2063
};
const request: unknown =
isOAuthToken && client.beta
? client.beta.messages.create(refreshParams, requestOptions)
: client.messages.create(refreshParams, requestOptions);
if (!hasAnthropicRawResponseRequest(request)) {
throw new AIError.AnthropicStreamEnvelopeError(
"Anthropic cache refresh request did not expose a raw response",
);
}
const response = await request.asResponse();
await notifyProviderResponse(options, response, model, response.headers.get("request-id"));
const body: unknown = await response.json();
if (!isRecord(body)) {
throw new AIError.AnthropicStreamEnvelopeError("Anthropic cache refresh returned a malformed response");
}
const wireUsage = parseAnthropicWireUsage(body.usage);
if (!wireUsage) {
throw new AIError.AnthropicStreamEnvelopeError("Anthropic cache refresh response omitted usage");
}
if (typeof body.id === "string") output.responseId = body.id;
output.usage.input = wireUsage.input_tokens ?? 0;
output.usage.output = wireUsage.output_tokens ?? 0;
output.usage.cacheRead = wireUsage.cache_read_input_tokens ?? 0;
output.usage.cacheWrite = wireUsage.cache_creation_input_tokens ?? 0;
applyAnthropicUsageExtras(output.usage, wireUsage);
output.usage.totalTokens =
output.usage.input + output.usage.output + output.usage.cacheRead + output.usage.cacheWrite;
calculateCost(model, output.usage);
output.duration = performance.now() - startTime;
stream.push({ type: "start", partial: output });
stream.push({ type: "done", reason: "stop", message: output });
stream.end();
return;
}
// Opt-in flag: the response parser only honors `fallback` contentView on GitHub (pinned to 9690622007)
Solutions
- Ensure the endpoint is a genuine Anthropic Messages API that returns a usage object with input_tokens/output_tokens.
- If using a gateway/emulator, upgrade it to one that forwards the Anthropic usage fields.
- Check the configured API version header for schema changes to `usage`.
- Update test mocks to include usage: { input_tokens, output_tokens } (plus cache counters when relevant).
Example fix
// before
{ id: "msg_1", type: "message", role: "assistant" } // no usage
// after
{
id: "msg_1", type: "message", role: "assistant",
usage: { input_tokens: 10, output_tokens: 5, cache_read_input_tokens: 0, cache_creation_input_tokens: 0 },
} Defensive patterns
Strategy: validation
Validate before calling
const body = await response.json();
const usage = body?.usage;
if (typeof usage !== "object" || usage === null ||
(typeof usage.input_tokens !== "number" && typeof usage.output_tokens !== "number")) {
throw new Error("Endpoint did not return Anthropic-style usage; check gateway/provider compatibility.");
} Type guard
function hasWireUsage(body: unknown): body is { usage: { input_tokens?: number; output_tokens?: number; cache_read_input_tokens?: number; cache_creation_input_tokens?: number } } {
return isRecord(body) && isRecord(body.usage) &&
("input_tokens" in body.usage || "output_tokens" in body.usage);
} Try / catch
try {
const usage = await refreshCacheUsage(params);
return usage;
} catch (err) {
if (err instanceof AIError.AnthropicStreamEnvelopeError && /omitted usage/.test(err.message)) {
return { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }; // degrade gracefully
} else {
throw err;
}
} Prevention
- Test gateways/emulators for usage passthrough before adopting them.
- Pin the Anthropic API version header and review changelogs for usage schema changes.
- Include usage fields (input_tokens, output_tokens, cache counters) in all refresh-response mocks.
- Monitor for endpoints that silently drop optional fields after upgrades.
When it happens
Trigger: The refresh response's `usage` field is missing, null, or lacks the expected counters (input_tokens/output_tokens) so parseAnthropicWireUsage returns null — e.g. a non-Anthropic endpoint or an error-shaped object returned with 200.
Common situations: Gateways that reshape or strip Anthropic responses; provider emulators (local LLM gateways) that omit usage; API version changes altering the usage schema; mocks that forget the usage object.
Related errors
- anthropic-messages: ${data.summary}
- Anthropic cache refresh request did not expose a raw respons
- Anthropic cache refresh returned a malformed response
- using '-' to denote standard input does not work in file sys
- Request was aborted.
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/a25958538730f159.
Report an issue: GitHub.