can1357/oh-my-pi · error
No response body for V2 compaction streaming
Error message
No response body for V2 compaction streaming
What it means
collectCompactionV2Output tries to obtain a reader from the HTTP response body to consume the SSE stream; if response.body is null there is nothing to stream and it throws. This happens when the runtime/fetch implementation produced a bodiless response (or the body was already consumed).
Source
Thrown at packages/agent/src/compaction/compaction-v2-streaming.ts:471
async function collectCompactionV2Events(
events: AsyncIterable<Record<string, unknown>>,
request: CompactionV2Request,
): Promise<CompactionV2Response> {
const state = createCompactionV2CollectionState();
for await (const event of events) {
handleCompactionV2Event(event, undefined, state);
}
return finishCompactionV2Collection(state, request);
}
async function collectCompactionV2Output(
response: Response,
request: CompactionV2Request,
): Promise<CompactionV2Response> {
const reader = response.body?.getReader();
if (!reader) {
throw new Error("No response body for V2 compaction streaming");
}
const state = createCompactionV2CollectionState();
try {
const decoder = new TextDecoder();
let buffer = "";
let eventName: string | undefined;
let dataLines: string[] = [];
const dispatch = (): void => {
if (dataLines.length === 0) {
eventName = undefined;
return;
}
handleCompactionV2SseEvent(dataLines.join("\n"), eventName, state);
eventName = undefined;
dataLines = [];
};View on GitHub (pinned to 9690622007)
Solutions
- Ensure the fetch implementation passes through the raw streaming Response untouched (don't read .text()/.json() first, don't return cached responses)
- If you must supply options.fetch, have it return a Response whose body is a readable stream (e.g. new Response(stream))
- Check no middleware locks or consumes response.body before collectCompactionV2Output runs
- Fall back to a non-streaming compaction path if the environment cannot provide streaming bodies
Example fix
// before
fetchImpl: async (url, init) => { const r = await fetch(url, init); await r.text(); return r; } // body consumed
// after
fetchImpl: (url, init) => fetch(url, init) // pass Response through untouched Defensive patterns
Strategy: validation
Validate before calling
const probe = await fetch(endpoint, init);
if (!probe.body) {
throw new Error("Compaction fetch impl must return a Response with a streaming body");
} Type guard
function hasStreamingBody(res: Response): boolean {
return res.body !== null && !res.bodyUsed;
} Prevention
- Never wrap fetch in ways that consume response.body before returning
- In tests, return new Response(stream) rather than Response without a body
- Ensure the runtime supports streaming response bodies (avoid stubs in workers/embeddings)
When it happens
Trigger: The fetch Response returned by the compaction endpoint has a null body — e.g. a custom fetch impl (options.fetch) that returns a cached/stubbed Response without a body, a body already read elsewhere, or a runtime/proxy stripping the streaming body.
Common situations: Custom fetch wrappers (logging, caching, retries) that consume or fail to pass through the body; mocking in tests returning new Response(null); undici/worker environments where streaming bodies are unsupported or already locked.
Related errors
- V2 remote compaction failed (${response.status} ${response.s
- V2 compaction stream closed before response.completed
- V2 compaction stream parse failed: ${err instanceof Error ?
- formatCompactionV2Failure(event, type)
- Bedrock response has no body
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/82233e7f49038fe5.
Report an issue: GitHub.