{"record":{"id":"05459bc3bdc94765","repo":"denoland/deno","slug":"err-http2-status-invalid-05459b","errorCode":"ERR_HTTP2_STATUS_INVALID","errorMessage":"Invalid status code: ${code}","messagePattern":"Invalid status code: (.+?)","errorType":"validation","errorClass":"NodeRangeError","httpStatus":null,"severity":"error","filePath":"ext/node/polyfills/internal/http2/compat.js","lineNumber":612,"sourceCode":"  get writableLength() {\n    return this[kStream].writableLength;\n  }\n\n  get writableObjectMode() {\n    return this[kStream].writableObjectMode;\n  }\n\n  get writableNeedDrain() {\n    return this[kStream].writableNeedDrain;\n  }\n\n  set statusCode(code) {\n    code |= 0;\n    if (code >= 100 && code < 200) {\n      throw new ERR_HTTP2_INFO_STATUS_NOT_ALLOWED();\n    }\n    if (code < 100 || code > 599) {\n      throw new ERR_HTTP2_STATUS_INVALID(code);\n    }\n    this[kState].statusCode = code;\n  }\n\n  setTrailer(name, value) {\n    validateString(name, \"name\");\n    name = StringPrototypeToLowerCase(StringPrototypeTrim(name));\n    assertValidHeader(name, value);\n    this[kTrailers][name] = value;\n  }\n\n  addTrailers(headers) {\n    const keys = ObjectKeys(headers);\n    let key = \"\";\n    for (let i = 0; i < keys.length; i++) {\n      key = keys[i];\n      this.setTrailer(key, headers[key]);\n    }","sourceCodeStart":594,"sourceCodeEnd":630,"githubUrl":"https://github.com/denoland/deno/blob/9ad36f7a2cce60488e6ec52283efb32efddaf93a/ext/node/polyfills/internal/http2/compat.js#L594-L630","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nres.statusCode = err.code; // err.code = 6003 -> ERR_HTTP2_STATUS_INVALID\n\n// after\nres.statusCode = err.httpStatus ?? 500; // map internal codes to real HTTP statuses","handlingStrategy":"validation","validationCode":"if (!(Number.isInteger(s) && s >= 100 && s <= 599)) s = 500;\nres.statusCode = s;","typeGuard":"function isValidHttpStatus(code: unknown): code is number {\n  return Number.isInteger(code) && code >= 100 && code <= 599;\n}","tryCatchPattern":"try {\n  res.statusCode = s;\n} catch (err) {\n  if (err.code === \"ERR_HTTP2_STATUS_INVALID\") res.statusCode = 500;\n  else throw err;\n}","preventionTips":["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"],"tags":["http2","status-code","validation"],"backgroundTag":"invalid-status-code","analyzedSha":"9ad36f7a2cce60488e6ec52283efb32efddaf93a","analyzedAt":"2026-08-20T13:07:44.778Z","contentChangedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}