websockets/ws · error · SyntaxError
Unexpected end of input
Error message
Unexpected end of input
What it means
Thrown by extension.parse() at end-of-input (extension.js:150-151) when the final state is invalid: either start is -1 (the header ended right after a separator with no trailing token), inQuotes is still true (an unclosed double-quoted string), or the last character was whitespace (trailing space/tab). All three indicate the header is truncated or incomplete per RFC 6455 §9.1.
Source
Thrown at lib/extension.js:151
mustUnescape = false;
}
push(params, paramName, value);
if (code === 0x2c) {
push(offers, extensionName, params);
params = Object.create(null);
extensionName = undefined;
}
paramName = undefined;
start = end = -1;
} else {
throw new SyntaxError(`Unexpected character at index ${i}`);
}
}
}
if (start === -1 || inQuotes || code === 0x20 || code === 0x09) {
throw new SyntaxError('Unexpected end of input');
}
if (end === -1) end = i;
const token = header.slice(start, end);
if (extensionName === undefined) {
push(offers, token, params);
} else {
if (paramName === undefined) {
push(params, token, true);
} else if (mustUnescape) {
push(params, paramName, token.replace(/\\/g, ''));
} else {
push(params, paramName, token);
}
push(offers, extensionName, params);
}
return offers;View on GitHub (pinned to ae1de54330)
Solutions
- Check whether the header ends with a separator (';'/',') and remove the trailing separator, or append the missing token.
- If a quoted value is unterminated, add the closing '"'.
- Remove trailing whitespace from the header value.
- If the truncation comes from the network/peer, investigate packet fragmentation or proxy modification.
Example fix
// before
const offers = WebSocket.extension.parse('permessage-deflate; x="abc');
// after — close the quoted string
const offers = WebSocket.extension.parse('permessage-deflate; x="abc"'); Defensive patterns
Strategy: try-catch
Validate before calling
// Reject truncated headers: trailing separators, trailing whitespace, unclosed quotes
function isCompleteHeader(header) {
const trimmed = header.trim();
if (/[;,]$/.test(trimmed)) return false;
if (trimmed.endsWith(' ') || trimmed.endsWith('\t')) return false;
const quoteCount = (trimmed.match(/"/g) || []).length;
if (quoteCount % 2 !== 0) return false;
return true;
}
if (isCompleteHeader(header)) {
const offers = WebSocket.extension.parse(header);
} Try / catch
try {
const offers = WebSocket.extension.parse(header);
} catch (err) {
if (err instanceof SyntaxError && err.message === 'Unexpected end of input') {
console.warn('Truncated extensions header:', header);
return;
}
throw err;
} Prevention
- Trim trailing whitespace and separators from header values before parsing.
- Ensure all quoted strings are closed with a matching '"'.
- Avoid constructing headers by concatenating fragments that may be empty.
- Catch the 'Unexpected end of input' SyntaxError specifically for truncated headers.
When it happens
Trigger: extension.parse() is called with a header that ends prematurely: 'permessage-deflate;' (trailing separator, start is -1 at end), 'permessage-deflate; x="abc' (unclosed quote, inQuotes is true), or 'permessage-deflate ' (trailing whitespace, last char was space).
Common situations: A truncated Sec-WebSocket-Extensions header from a network read that cut off mid-value. A developer's string-building code forgets to append the closing quote or final token. A header value that was trimmed or corrupted by a proxy.
Related errors
- Unexpected character at index ${i}
- Unexpected character at index ${i}
- The "${protocol}" subprotocol is duplicated
- Unexpected end of input
- None of the extension offers can be accepted
AI-assisted analysis of websockets/ws@ae1de54330 (2026-08-03).
Data as JSON: /data/errors/09e75ef415ffc20c.json.
Report an issue: GitHub.