decolua/9router · error
AWS EventStream frame is shorter than 16 bytes
Error message
AWS EventStream frame is shorter than 16 bytes
What it means
The Kiro executor's parseEventFrame() decodes AWS EventStream binary frames, which always begin with a 12-byte prelude (total length, headers length, CRC) plus a 4-byte message CRC — 16 bytes minimum. This error is thrown when the buffer handed to the parser is not a Uint8Array or contains fewer than 16 bytes, meaning it cannot possibly hold a complete frame. It is a fail-fast integrity check on the upstream Kiro (CodeWhisperer) EventStream transport.
Source
Thrown at open-sse/executors/kiro.js:1198
log,
proxyOptions
);
return result;
} catch (error) {
log?.error?.("TOKEN", `Kiro refresh error: ${error.message}`);
return null;
}
}
}
/**
* 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");
}View on GitHub (pinned to 90b52e06ff)
Solutions
- Re-stream/accumulate bytes and only hand complete frames to parseEventFrame (ensure the caller buffers partial chunks until totalLength bytes are available).
- Retry the Kiro request — a truncated frame usually means the upstream connection was dropped mid-stream.
- Check for a proxy (HTTP_PROXY/HTTPS_PROXY or corporate MITM) corrupting binary EventStream bodies and bypass it for the Kiro endpoint.
- Verify the Kiro credentials/account are valid; an auth failure can produce a non-EventStream body that fragments into tiny chunks.
- Update 9router — upstream protocol changes may require a newer executor/translator.
Example fix
// before: parsing raw network chunks directly
for (const chunk of chunks) parseEventFrame(chunk);
// after: buffer until a full frame is available
let buf = new Uint8Array(0);
for (const chunk of chunks) {
buf = concat(buf, chunk);
if (buf.byteLength >= 16) {
const totalLength = new DataView(buf.buffer).getUint32(0, false);
if (buf.byteLength >= totalLength) {
parseEventFrame(buf.subarray(0, totalLength));
buf = buf.subarray(totalLength);
}
}
} Defensive patterns
Strategy: validation
Validate before calling
function isCompleteEventStreamFrame(data) {
return data instanceof Uint8Array &&
data.byteLength >= 16 &&
new DataView(data.buffer, data.byteOffset, data.byteLength).getUint32(0, false) === data.byteLength;
}
if (isCompleteEventStreamFrame(buf)) parseEventFrame(buf); Type guard
function isFrameCandidate(v) {
return v instanceof Uint8Array && v.byteLength >= 16;
} Try / catch
try {
parseEventFrame(frame);
} catch (e) {
if (e.message.includes('shorter than 16 bytes')) {
log.warn('kiro: truncated frame, reconnecting');
await retryRequest();
} else throw e;
} Prevention
- Always accumulate stream chunks and only parse when byteLength >= 16 AND byteLength >= prelude totalLength.
- Never parse raw reader chunks directly — route them through a frame-boundary assembler.
- Treat a sub-16-byte chunk at stream end as a truncation signal and retry, not as a fatal bug.
- Test the executor against artificially truncated bodies to confirm graceful handling.
When it happens
Trigger: parseEventFrame() receives a Uint8Array with byteLength < 16, or a non-Uint8Array value, from the network chunk assembler feeding it — typically a partial/truncated frame fragment at the start or end of the HTTP/2 body stream from the Kiro upstream.
Common situations: Upstream connection cut mid-frame (proxy, network blip, idle timeout); a buffering bug where stream chunks are passed to the parser before being accumulated to full-frame boundaries; a MITM/intercepting proxy mangling the binary body; Kiro returning an error page or empty body instead of an EventStream.
Related errors
- AWS EventStream frame length does not match its prelude
- Kiro toolUseEvent is empty
- Kiro toolUseEvent is missing a tool name
- Kiro toolUseEvent has an invalid toolUseId
- Kiro tool name changed between fragments
AI-assisted analysis of decolua/9router@90b52e06ff (2026-08-30).
Data as JSON: /api/errors/0827a022cec06feb.
Report an issue: GitHub.