denoland/deno · error · NodeRangeError
ERR_HTTP2_STATUS_INVALID
ERR_HTTP2_STATUS_INVALID
Error message
Invalid status code: ${code} What it means
The same statusCode setter throws ERR_HTTP2_STATUS_INVALID for any value outside 100-599 after the bitwise `code |= 0` coercion. Values like 99, 600, or strings coercing to 0/NaN fail; fractional numbers are silently truncated by the coercion before the range check.
Source
Thrown at ext/node/polyfills/internal/http2/compat.js:612
get writableLength() {
return this[kStream].writableLength;
}
get writableObjectMode() {
return this[kStream].writableObjectMode;
}
get writableNeedDrain() {
return this[kStream].writableNeedDrain;
}
set statusCode(code) {
code |= 0;
if (code >= 100 && code < 200) {
throw new ERR_HTTP2_INFO_STATUS_NOT_ALLOWED();
}
if (code < 100 || code > 599) {
throw new ERR_HTTP2_STATUS_INVALID(code);
}
this[kState].statusCode = code;
}
setTrailer(name, value) {
validateString(name, "name");
name = StringPrototypeToLowerCase(StringPrototypeTrim(name));
assertValidHeader(name, value);
this[kTrailers][name] = value;
}
addTrailers(headers) {
const keys = ObjectKeys(headers);
let key = "";
for (let i = 0; i < keys.length; i++) {
key = keys[i];
this.setTrailer(key, headers[key]);
}View on GitHub (pinned to 9ad36f7a2c)
Solutions
- Validate with Number.isInteger(code) && code >= 100 && code <= 599 before assigning
- Map non-HTTP internal codes to a real class (usually 500) plus a machine-readable body field
- Parse statuses from external input with parseInt and a range check
Example fix
// before res.statusCode = err.code; // err.code = 6003 -> ERR_HTTP2_STATUS_INVALID // after res.statusCode = err.httpStatus ?? 500; // map internal codes to real HTTP statuses
Defensive patterns
Strategy: validation
Validate before calling
if (!(Number.isInteger(s) && s >= 100 && s <= 599)) s = 500; res.statusCode = s;
Type guard
function isValidHttpStatus(code: unknown): code is number {
return Number.isInteger(code) && code >= 100 && code <= 599;
} Try / catch
try {
res.statusCode = s;
} catch (err) {
if (err.code === "ERR_HTTP2_STATUS_INVALID") res.statusCode = 500;
else throw err;
} Prevention
- Keep internal error codes out of HTTP status fields; translate them at the edge
- Assert the 100-599 range in one shared helper used by every handler
When it happens
Trigger: response.statusCode = 600 (custom 'edge' code); statusCode = "ok" or "404?" coercing to NaN/0; computed statuses (base + offset) slipping past 599; truthy-but-invalid values from untyped config.
Common situations: Internal application error codes above 599 leaking into responses; statuses parsed from headers/query as strings without conversion; off-by-one errors in status mapping tables.
Related errors
- The status provided (${init.status}) is not equal to 101 and
- ERR_HTTP2_STATUS_INVALID
- ERR_HTTP2_STATUS_101
- ERR_HTTP2_INVALID_INFO_STATUS
- ERR_HTTP2_INVALID_PACKED_SETTINGS_LENGTH
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/05459bc3bdc94765.
Report an issue: GitHub.