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

  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.