can1357/oh-my-pi · error

V2 compaction stream parse failed

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.

Solutions

  1. Log the offending data frame (the embedded parse error / raw payload) to see what the server actually sent
  2. Check for proxies/WAF/gateways injecting non-JSON content into the SSE stream and bypass or fix them
  3. Ensure the response is consumed as a byte stream decoded incrementally (TextDecoder over reader chunks), not re-split incorrectly by custom plumbing
  4. 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

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


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/4a59e0756f266e1e. Report an issue: GitHub.

Appendix: 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)