paperclipai/paperclip · error
OpenCode SSE event exceeded the retained payload limit
Error message
OpenCode SSE event exceeded the retained payload limit
What it means
Thrown while parsing the OpenCode SSE stream when the accumulated buffer of a single un-terminated SSE event exceeds 1,048,576 bytes (1 MiB). The driver caps retained payload size to prevent unbounded memory growth from a misbehaving or malicious server.
Source
Thrown at packages/paperclip-runner/src/drivers/opencode/opencode-server-driver.ts:2409
const address = server.address();
if (!address || typeof address === "string")
throw new Error("Unable to reserve OpenCode port");
const port = address.port;
await new Promise<void>((resolve, reject) =>
server.close((error) => (error ? reject(error) : resolve())),
);
return port;
}
async function* parseSseFrames(
stream: ReadableStream<Uint8Array>,
): AsyncIterable<{ raw: string; data: string }> {
const decoder = new TextDecoder();
let buffer = "";
for await (const chunk of stream as unknown as AsyncIterable<Uint8Array>) {
buffer += decoder.decode(chunk, { stream: true });
if (buffer.length > 1_048_576)
throw new Error("OpenCode SSE event exceeded the retained payload limit");
let boundary: RegExpExecArray | null;
while ((boundary = /\r?\n\r?\n/.exec(buffer)) !== null) {
const rawFrame = buffer.slice(0, boundary.index);
const raw = buffer.slice(0, boundary.index + boundary[0].length);
const frame = rawFrame.replaceAll("\r", "");
buffer = buffer.slice(boundary.index + boundary[0].length);
const data = frame
.split("\n")
.filter((line) => line.startsWith("data:"))
.map((line) => line.slice(5).trimStart())
.join("\n");
if (!data || data === "[DONE]") continue;
yield { raw, data };
}
}
}
async function* parseSse(View on GitHub (pinned to 01ad858492)
Solutions
- Inspect what the server actually sent at that point — if it is HTML/JSON error content, the endpoint path or auth is wrong, not the payload size.
- Check whether a proxy/gateway is buffering or mangling the SSE stream so frame boundaries are lost.
- Reduce the size of provider events (e.g. huge tool outputs) so individual events stay under 1 MiB.
- If legitimate events can exceed 1 MiB, raise the limit in the SSE parser and document the memory trade-off.
Example fix
// before
if (buffer.length > 1_048_576)
throw new Error("OpenCode SSE event exceeded the retained payload limit");
// after
const SSE_MAX_BUFFER = 4 * 1_048_576; // allow large tool outputs
if (buffer.length > SSE_MAX_BUFFER)
throw new Error(`OpenCode SSE event exceeded ${SSE_MAX_BUFFER} bytes`); Defensive patterns
Strategy: try-catch
Try / catch
try {
for await (const frame of sseFrames(stream)) consume(frame);
} catch (e) {
if (e instanceof Error && e.message.includes("retained payload limit")) {
// dump first bytes of raw stream to see what the server actually sent (HTML? giant event?)
}
} Prevention
- Verify the event endpoint returns text/event-stream, not HTML/JSON error content
- Keep individual provider events (tool outputs) under 1 MiB
- Ensure proxies do not strip SSE frame boundaries or mis-handle compression
When it happens
Trigger: A streamed chunk sequence where no \r?\n\r?\n frame boundary appears and buffered data surpasses 1 MiB — e.g. the server sends one giant event, garbage data without blank-line separators, or a binary (non-SSE) response body.
Common situations: Proxy returning a non-SSE HTML page (no frame boundaries); server emitting a single very large tool-output event; corrupted stream due to compression not being decompressed.
Understand the failure class
Background: payload too large / request exceeds maximum size: why libraries cap bytes and how to fix oversize payloads — this error's family across 50 libraries.
Related errors
- The bridge host reached its reserved process body byte ceili
- OpenCode event stream returned HTTP ${response.status}
- OpenCode event stream closed before the session became termi
- github_attachment_canonical_api_too_large
- dropping 1 event whose serialized envelope exceeds maxBodyBy
AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-10).
Data as JSON: /api/errors/a3c21fc0f7dbc7c7.
Report an issue: GitHub.