can1357/oh-my-pi · error
V2 compaction stream parse failed: ${err instanceof Error ?
Error message
V2 compaction stream parse failed: ${err instanceof Error ? err.message : String(err)} What it means
A SSE data frame from the V2 compaction stream failed JSON.parse (and was not the literal [DONE] sentinel). The parse error message is embedded and rethrown so the failure points at the actual malformed frame rather than crashing deep in event handling.
Source
Thrown at packages/agent/src/compaction/compaction-v2-streaming.ts:562
compactionItem,
replacementHistory,
usedTokens: state.usage?.inputTokens ?? 0,
usage: state.usage,
retainedImageCount,
};
}
function handleCompactionV2SseEvent(
data: string,
eventName: string | undefined,
state: CompactionV2CollectionState,
): void {
if (data === "[DONE]") return;
let event: Record<string, unknown>;
try {
event = JSON.parse(data) as Record<string, unknown>;
} catch (err) {
throw new Error(`V2 compaction stream parse failed: ${err instanceof Error ? err.message : String(err)}`);
}
handleCompactionV2Event(event, eventName, state);
}
function handleCompactionV2Event(
event: Record<string, unknown>,
eventName: string | undefined,
state: CompactionV2CollectionState,
): void {
const type = typeof event.type === "string" ? event.type : eventName;
if (type === "response.output_item.done") {
state.outputItemCount++;
const item = event.item;
if (isRecord(item) && item.type === "compaction") {
state.compactionItems.push(item);
}
return;
}View on GitHub (pinned to 9690622007)
Solutions
- Log the offending data frame (the embedded parse error / raw payload) to see what the server actually sent
- Check for proxies/WAF/gateways injecting non-JSON content into the SSE stream and bypass or fix them
- Ensure the response is consumed as a byte stream decoded incrementally (TextDecoder over reader chunks), not re-split incorrectly by custom plumbing
- Retry the compaction; if it reproduces deterministically, verify you are hitting the compaction endpoint with valid auth
Example fix
// before
const text = await response.text(); text.split("\n") // mangles SSE frames
// after
const reader = response.body!.getReader();
// decode incrementally with TextDecoder and split on \n\n event boundaries Defensive patterns
Strategy: retry
Try / catch
try {
return await requestCompactionV2Streaming({ model, ... });
} catch (err) {
if (err instanceof Error && err.message.startsWith("V2 compaction stream parse failed")) {
logRawSseFramesOnce(); // capture the offending frame
await Bun.sleep(backoff);
return requestCompactionV2Streaming({ model, ... });
}
throw err;
} Prevention
- Bypass or fix proxies/WAFs that inject HTML/plain-text into SSE streams
- Consume responses as incremental byte streams with TextDecoder; never re-split cached text
- Retry transient parse failures; investigate persistent ones at the network layer
When it happens
Trigger: The endpoint (or an intermediary proxy) emits a data line that is not valid JSON — e.g. an HTML error page chunk, a plain-text gateway error, truncated JSON from a dropped connection, or multi-frame data split/reassembled incorrectly by a proxy.
Common situations: Auth proxies returning HTML 'login required' bodies with 200; CDN/WAF injecting error text mid-stream; keep-alive comments misinterpreted as data; custom fetch wrappers mangling the byte stream (wrong decoding/chunk boundaries).
Understand the failure class
Background: "Invalid JSON response" and "Failed to parse response" errors: when an API answers 200 but the body isn't the JSON your library expected — this error's family across 28 libraries.
Related errors
- V2 compaction stream closed before response.completed
- Unexpected token at position ${this.#i}
- Replacement text is not valid UTF-8: {err}
- No response body for V2 compaction streaming
- formatCompactionV2Failure(event, type)
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/4a59e0756f266e1e.
Report an issue: GitHub.