decolua/9router · error
AWS EventStream frame bounds are invalid
Error message
AWS EventStream frame bounds are invalid
What it means
After the prelude passes basic consistency checks, parseEventFrame() sanity-checks the declared totalLength against EVENTSTREAM_MAX_MESSAGE_BYTES, the headersLength against EVENTSTREAM_MAX_HEADERS_BYTES, and requires headersLength to fit within totalLength - 16 (prelude + CRC). This is a resource-exhaustion / malicious-payload guard: an absurd length would otherwise drive huge allocations or out-of-bounds header parsing.
Source
Thrown at open-sse/executors/kiro.js:1209
/**
* Parse AWS EventStream frame
*/
function parseEventFrame(data) {
if (!(data instanceof Uint8Array) || data.byteLength < 16) {
throw new Error("AWS EventStream frame is shorter than 16 bytes");
}
const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
const totalLength = view.getUint32(0, false);
const headersLength = view.getUint32(4, false);
if (totalLength !== data.byteLength) {
throw new Error("AWS EventStream frame length does not match its prelude");
}
if (totalLength > EVENTSTREAM_MAX_MESSAGE_BYTES ||
headersLength > EVENTSTREAM_MAX_HEADERS_BYTES ||
headersLength > totalLength - 16) {
throw new Error("AWS EventStream frame bounds are invalid");
}
if (view.getUint32(8, false) !== crc32(data.subarray(0, 8))) {
throw new Error("AWS EventStream prelude CRC mismatch");
}
if (view.getUint32(totalLength - 4, false) !== crc32(data.subarray(0, totalLength - 4))) {
throw new Error("AWS EventStream message CRC mismatch");
}
const headers = Object.create(null);
const names = new Set();
let offset = 12;
const headerEnd = offset + headersLength;
const requireBytes = (count) => {
if (offset + count > headerEnd) {
throw new Error("AWS EventStream header exceeds its declared bounds");
}
};
View on GitHub (pinned to 90b52e06ff)
Solutions
- Re-sync stream parsing: after each frame, advance exactly totalLength bytes so payload bytes are never misread as the next prelude.
- Retry the request — random corruption points to the transport, not the frame format.
- Bypass MITM/transforming proxies (or TLS-inspecting firewalls) for the Kiro endpoint.
- If legitimate frames exceed the caps, raise EVENTSTREAM_MAX_MESSAGE_BYTES / EVENTSTREAM_MAX_HEADERS_BYTES in open-sse config for very large tool_result payloads.
- Verify the Kiro base URL points at the real CodeWhisperer/Kiro EventStream endpoint, not an HTML error page.
Defensive patterns
Strategy: validation
Validate before calling
function frameBoundsOk(data, MAX_MSG, MAX_HDR) {
if (!(data instanceof Uint8Array) || data.byteLength < 16) return false;
const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
const total = view.getUint32(0, false), hdr = view.getUint32(4, false);
return total === data.byteLength && total <= MAX_MSG && hdr <= MAX_HDR && hdr <= total - 16;
}
if (frameBoundsOk(buf, EVENTSTREAM_MAX_MESSAGE_BYTES, EVENTSTREAM_MAX_HEADERS_BYTES)) parseEventFrame(buf); Type guard
function hasSanePrelude(v) {
if (!(v instanceof Uint8Array) || v.byteLength < 16) return false;
const view = new DataView(v.buffer, v.byteOffset, v.byteLength);
const total = view.getUint32(0, false), hdr = view.getUint32(4, false);
return total <= 0x4000000 && hdr <= total - 16;
} Try / catch
try {
parseEventFrame(frame);
} catch (e) {
if (e.message.includes('bounds are invalid')) {
log.error('kiro: insane frame bounds, possible desync or MITM');
cancelAndResyncStream();
} else throw e;
} Prevention
- Verify the endpoint really speaks EventStream — parse only bodies with content-type application/vnd.amazon.eventstream or similar.
- Never feed non-stream bytes (HTML error pages, JSON error bodies) into the binary parser; check response status/content-type first.
- Keep prelude caps (EVENTSTREAM_MAX_MESSAGE_BYTES/HEADERS_BYTES) in sync with real upstream frame sizes.
- After a bounds failure, assume stream desync and resynchronize rather than continuing to parse.
When it happens
Trigger: A corrupted or hostile frame declares a totalLength or headersLength beyond configured maxima, or headersLength so large it cannot fit inside the frame (headersLength > totalLength - 16) — e.g. random bytes interpreted as a prelude, or a length field flipped by transmission corruption.
Common situations: Connecting to a non-EventStream endpoint or a proxy error page whose bytes are misparsed as a prelude; a man-in-the-middle rewriting binary bodies; desynced stream parsing where a payload's bytes are consumed as a new frame header; memory-limit misconfiguration making legit huge frames exceed EVENTSTREAM_MAX_MESSAGE_BYTES.
Related errors
- AWS EventStream frame is shorter than 16 bytes
- AWS EventStream frame length does not match its prelude
- AWS EventStream prelude CRC mismatch
- AWS EventStream message CRC mismatch
- AWS EventStream header exceeds its declared bounds
AI-assisted analysis of decolua/9router@90b52e06ff (2026-08-30).
Data as JSON: /api/errors/beb60a2d2d8431ac.
Report an issue: GitHub.