can1357/oh-my-pi · error

V2 compaction stream closed before response.completed

Error message

V2 compaction stream closed before response.completed

What it means

The SSE stream from the V2 compaction endpoint terminated without ever delivering a response.completed event (state.sawCompleted false), so the collected data cannot be trusted as a finished compaction. This guards against accepting partial results from a truncated or dropped connection.

Source

Thrown at packages/agent/src/compaction/compaction-v2-streaming.ts:529

				dataLines.push(buffer.slice("data:".length).trimStart());
			} else if (buffer.startsWith("event:")) {
				eventName = buffer.slice("event:".length).trim();
			}
		}
		dispatch();
	} finally {
		reader.releaseLock();
	}

	return finishCompactionV2Collection(state, request);
}

function finishCompactionV2Collection(
	state: CompactionV2CollectionState,
	request: CompactionV2Request,
): CompactionV2Response {
	if (!state.sawCompleted) {
		throw new Error("V2 compaction stream closed before response.completed");
	}
	if (state.compactionItems.length !== 1) {
		throw new Error(
			`V2 compaction expected exactly one compaction output item, got ${state.compactionItems.length} from ${state.outputItemCount} output items`,
		);
	}

	const compactionItem = state.compactionItems[0];
	const { replacementHistory, retainedImageCount } = buildCompactionV2ReplacementHistory(
		request.input,
		compactionItem,
		request.retainedMessageBudget,
	);
	return {
		compactionItem,
		replacementHistory,
		usedTokens: state.usage?.inputTokens ?? 0,
		usage: state.usage,

View on GitHub (pinned to 9690622007)

Solutions

  1. Retry the compaction — requestCompactionV2Streaming's retry logic (retryWait option) is designed for transient stream drops
  2. Increase proxy/gateway idle timeouts for the compaction endpoint to exceed expected compaction duration
  3. Disable response buffering on intermediaries (e.g. proxy_buffering off for nginx) so SSE events flow
  4. Check server logs/status for early connection termination; if persistent, fall back to local compaction

Example fix

// before
await requestCompactionV2Streaming({ model, ... }); // stream drops behind 60s proxy timeout
// after
await requestCompactionV2Streaming({ model, retryWait: (ms) => Bun.sleep(ms), ... });
// plus: nginx: proxy_read_timeout 600s; proxy_buffering off;
Defensive patterns

Strategy: retry

Validate before calling

// keep intermediary timeouts longer than worst-case compaction
// e.g. nginx: proxy_read_timeout 600s; proxy_buffering off;

Try / catch

try {
  return await requestCompactionV2Streaming({ model, ... });
} catch (err) {
  if (err instanceof Error && err.message.includes("closed before response.completed")) {
    await Bun.sleep(backoff);
    return requestCompactionV2Streaming({ model, ... }); // transient drop: retry
  }
  throw err;
}

Prevention

When it happens

Trigger: Connection drops mid-stream, server closes the SSE connection after an error without response.failed, a proxy/load-balancer times out the long-running stream, or [DONE] arrives before any response.completed event.

Common situations: Long compaction requests crossing proxy idle timeouts (e.g. 60s gateways); network interruptions on mobile/VPN; Azure OpenAI closing streams under load; misconfigured reverse proxy buffering/killing SSE.

Related errors


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