{"record":{"id":"03056f6bb3f4c264","repo":"denoland/deno","slug":"err-invalid-arg-type-03056f","errorCode":"ERR_INVALID_ARG_TYPE","errorMessage":"The \"statusCode\" argument must be of type integer [100, 999]. Received ${statusCode}","messagePattern":"The \"statusCode\" argument must be of type integer \\[100, 999\\]\\. Received (.+?)","errorType":"exception","errorClass":"NodeTypeError","httpStatus":null,"severity":"error","filePath":"ext/node/polyfills/_http_server.js","lineNumber":509,"sourceCode":"  this._writeRaw(head, \"ascii\", cb);\n};\n\nServerResponse.prototype._implicitHeader = function _implicitHeader() {\n  this.writeHead(this.statusCode);\n};\n\nServerResponse.prototype.writeHead = function writeHead(\n  statusCode,\n  reason,\n  obj,\n) {\n  if (this._header) {\n    throw new ERR_HTTP_HEADERS_SENT(\"write\");\n  }\n\n  statusCode |= 0;\n  if (statusCode < 100 || statusCode > 999) {\n    throw new ERR_INVALID_ARG_TYPE(\n      \"statusCode\",\n      \"integer [100, 999]\",\n      statusCode,\n    );\n  }\n\n  if (typeof reason === \"string\") {\n    this.statusMessage = reason;\n  } else {\n    this.statusMessage ||= STATUS_CODES[statusCode] || \"unknown\";\n    obj ??= reason;\n  }\n  this.statusCode = statusCode;\n\n  // Enforce no body for 204 and 304 responses\n  if (statusCode === 204 || statusCode === 304) {\n    this._hasBody = false;\n  }","sourceCodeStart":491,"sourceCodeEnd":527,"githubUrl":"https://github.com/denoland/deno/blob/89f33cbef296a2b287f323d42de54c871fa69c77/ext/node/polyfills/_http_server.js#L491-L527","documentation":"writeHead coerces statusCode with statusCode |= 0 and then requires the range 100..999. Values outside it throw ERR_INVALID_ARG_TYPE asking for 'integer [100, 999]' (Node's quirk: an out-of-range status uses the arg-type error code). NaN|0 and undefined|0 both become 0, so missing or unparseable statuses fail here too.","triggerScenarios":"res.writeHead(99), res.writeHead(1000), res.writeHead(NaN), res.writeHead(undefined), or res.writeHead('abc') (coerces to 0); a status computed from config, headers, or query params without validation.","commonSituations":"Status read from a config file or proxied header (Number(req.headers['x-status']) producing NaN); typos like 2000; a missing value defaulting to 0 instead of 200; arithmetic on optional fields yielding NaN.","solutions":["Validate the status is an integer in [100, 999] before calling writeHead, defaulting to 200 otherwise","Fix the producer of the bad value (config parsing, Number() on user input)","Never forward raw Number(userInput) results into the status","Whitelist allowed statuses per endpoint"],"exampleFix":"// before\nconst code = Number(req.query.status); // NaN or out of range\nres.writeHead(code);\n\n// after\nconst parsed = Number(req.query.status);\nconst code = Number.isInteger(parsed) && parsed >= 100 && parsed <= 999 ? parsed : 200;\nres.writeHead(code);","handlingStrategy":"validation","validationCode":"function validStatusCode(code) {\n  return Number.isInteger(code) && code >= 100 && code <= 999;\n}\nconst status = validStatusCode(raw) ? raw : 200;\nres.writeHead(status);","typeGuard":"function isStatusCode(v) {\n  return typeof v === 'number' && Number.isInteger(v) && v >= 100 && v <= 999;\n}","tryCatchPattern":"try {\n  res.writeHead(code);\n} catch (e) {\n  if (e.code === 'ERR_INVALID_ARG_TYPE' && /statusCode/.test(e.message)) {\n    res.writeHead(200);\n  } else throw e;\n}","preventionTips":["Never forward raw Number(userInput) into writeHead","Keep a per-endpoint whitelist of allowed statuses","Unit-test handlers with edge statuses 99, 100, 999, 1000 and NaN"],"tags":["http","validation","node-compat"],"backgroundTag":null,"analyzedSha":"89f33cbef296a2b287f323d42de54c871fa69c77","analyzedAt":"2026-08-16T07:54:21.310Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}