can1357/oh-my-pi · error · AnthropicStreamEnvelopeError
Anthropic SDK request did not expose a stream response
Error message
Anthropic SDK request did not expose a stream response
What it means
This AnthropicStreamEnvelopeError is thrown when the SDK request promise returned by the Anthropic client does not implement the withResponse() contract the library relies on. The library needs the raw HTTP response (headers, request id) alongside the decoded event stream, so a request without this surface cannot be observed.
Source
Thrown at packages/ai/src/providers/anthropic.ts:1519
events: AsyncIterable<AnthropicStreamEvent>;
response: Response;
requestId: string | null;
recordsRawSseEvents: boolean;
}> {
if (hasAnthropicRawResponseRequest(request)) {
const response = await request.asResponse();
return {
events: iterateAnthropicEvents(response, signal, onSseEvent),
response,
requestId: response.headers.get("request-id"),
recordsRawSseEvents: true,
};
}
if (hasAnthropicStreamWithResponseRequest(request)) {
const { data, response, request_id } = await request.withResponse();
return { events: data, response, requestId: request_id, recordsRawSseEvents: false };
}
throw new AIError.AnthropicStreamEnvelopeError("Anthropic SDK request did not expose a stream response");
}
async function* observeDecodedAnthropicSdkEvents(
events: AsyncIterable<AnthropicStreamEvent>,
observer: (event: RawSseEvent) => void,
): AsyncGenerator<AnthropicStreamEvent> {
for await (const event of events) {
const data = JSON.stringify(event);
// Reconstructed from decoded SDK event; not literal wire bytes.
notifyRawSseEvent(observer, { event: event.type, data, raw: [`event: ${event.type}`, `data: ${data}`] });
yield event;
}
}
const PROVIDER_MAX_RETRIES = 10;
/**
* Flat delay between attempts when Copilot 400s a model its own `/models`View on GitHub (pinned to 9690622007)
Solutions
- Upgrade or align @anthropic-ai/sdk to the version this library expects so stream requests expose withResponse().
- If mocking in tests, implement withResponse() returning { data, response, request_id }.
- Verify the raw client instance (not a partially wrapped object) is passed to the streaming path.
- Check hasAnthropicStreamWithResponseRequest expectations against the SDK's actual API surface in node_modules.
Example fix
// before
messages: { create: async () => eventStream } // no withResponse
// after
messages: {
create: async () => ({
[Symbol.asyncIterator]: eventStream[Symbol.asyncIterator].bind(eventStream),
withResponse: async () => ({ data: eventStream, response: rawResponse, request_id: "req_1" }),
}),
} Defensive patterns
Strategy: type-guard
Validate before calling
function isStreamRequestWithResponse(req: unknown): req is { withResponse(): Promise<{ data: AsyncIterable<unknown>; response: Response; request_id?: string }> } {
return typeof req === "object" && req !== null && "withResponse" in req && typeof (req as { withResponse?: unknown }).withResponse === "function";
}
// check before handing the SDK request to the streaming path Type guard
const request = client.messages.create(params, options);
if (typeof (request as { withResponse?: unknown }).withResponse !== "function") {
throw new Error("Anthropic SDK does not expose withResponse(); upgrade @anthropic-ai/sdk.");
} Try / catch
try {
const { events, response } = await request.withResponse();
return { events, response };
} catch (err) {
if (err instanceof AIError.AnthropicStreamEnvelopeError && /did not expose a stream response/.test(err.message)) {
// fall back to a manual fetch SSE request to the messages endpoint
} else {
throw err;
}
} Prevention
- Pin @anthropic-ai/sdk to a version range compatible with this library and test upgrades in CI.
- Keep SDK mocks complete: implement withResponse(), not just the async iterator.
- Avoid proxies/wrappers around the client that strip SDK request methods.
- Check the SDK changelog when bumping versions for return-type changes on messages.create.
When it happens
Trigger: Calling the streaming path with an Anthropic SDK client whose messages.create result lacks the withResponse() method (hasAnthropicStreamWithResponseRequest returns false) — typically a different/incompatible SDK version, a mock, or a non-SDK object passed where the client's request promise is expected.
Common situations: Pinning an older or forked @anthropic-ai/sdk that changed the return type; mocking client.messages.create with a plain AsyncIterable in tests; wrapping the client in a proxy that drops methods; using a gateway SDK that mimics but does not match the official API.
Related errors
- Anthropic cache refresh request did not expose a raw respons
- Attempted to iterate over an Anthropic response with no body
- received ${event.type} before message_start
- AbortError
- stream ended before message_stop
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/13a94ef7482f6d39.
Report an issue: GitHub.