expressjs/express · error · TypeError

Invalid status code: ${JSON.stringify(code)}. Status code mu

Error message

Invalid status code: ${JSON.stringify(code)}. Status code must be an integer.

What it means

res.status(code) in Express 5 strictly validates its argument: lib/response.js:67-68 throws a TypeError if the code is not an integer (a separate RangeError at line 71-72 covers integers outside 100-999). Express 4 silently coerced values like '200' or floats; Express 5 made this a hard error, so the JSON.stringify in the message shows you exactly what invalid value arrived.

Source

Thrown at lib/response.js:68

module.exports = res

/**
 * Set the HTTP status code for the response.
 *
 * Expects an integer value between 100 and 999 inclusive.
 * Throws an error if the provided status code is not an integer or if it's outside the allowable range.
 *
 * @param {number} code - The HTTP status code to set.
 * @return {ServerResponse} - Returns itself for chaining methods.
 * @throws {TypeError} If `code` is not an integer.
 * @throws {RangeError} If `code` is outside the range 100 to 999.
 * @public
 */

res.status = function status(code) {
  // Check if the status code is not an integer
  if (!Number.isInteger(code)) {
    throw new TypeError(`Invalid status code: ${JSON.stringify(code)}. Status code must be an integer.`);
  }
  // Check if the status code is outside of Node's valid range
  if (code < 100 || code > 999) {
    throw new RangeError(`Invalid status code: ${JSON.stringify(code)}. Status code must be greater than 99 and less than 1000.`);
  }

  this.statusCode = code;
  return this;
};

/**
 * Set Link header field with the given `links`.
 *
 * Examples:
 *
 *    res.links({
 *      next: 'http://api.example.com/users?page=2',
 *      last: 'http://api.example.com/users?page=5',

View on GitHub ↗ (pinned to a3714473fe)

Solutions

  1. Pass an integer: res.status(404), or convert explicitly with Number.parseInt(value, 10) and validate the result.
  2. In error handlers, default missing codes: res.status(Number.isInteger(err.status) ? err.status : 500).
  3. Audit call sites after an Express 4→5 upgrade for string status codes (the JSON.stringify output in the message tells you whether you got a string, undefined, or a float).

Example fix

// before (worked in Express 4)
res.status(err.status || '500').send(err.message);
// after
const code = Number.isInteger(err.status) ? err.status : 500;
res.status(code).send(err.message);
Defensive patterns

Strategy: type-guard

Validate before calling

if (!Number.isInteger(code) || code < 100 || code > 599) {
  throw new RangeError(`invalid HTTP status code: ${JSON.stringify(code)}`);
}
res.status(code);

Type guard

function isValidStatusCode(code) {
  return Number.isInteger(code) && code >= 100 && code <= 599;
}

Try / catch

try {
  res.status(upstream.statusCode).send(body);
} catch (err) {
  if (/Invalid status code/.test(err.message)) {
    // non-integer (string, undefined, float) reached res.status — normalize and fall back to 502/500
    return res.status(502).send('Bad upstream status');
  }
  throw err;
}

Prevention

When it happens

Trigger: res.status('404') or res.status(`${code}`) — numeric strings are no longer accepted; res.status(undefined) when an upstream error object lacks .status/.statusCode; res.status(err.statusCode) where the property is a string set by a proxy or older library; res.status(200.5) or NaN from arithmetic.

Common situations: Express 4→5 migration is the dominant cause: code that passed string status codes worked for years and breaks on upgrade; error-handler middleware doing res.status(err.status) where err.status is undefined for plain Errors; status codes read from route params, JSON payloads, or env vars without Number conversion.

Related errors


AI-assisted analysis of expressjs/express@a3714473fe (2026-07-31). Data as JSON: /data/errors/0f00a944d7a1f9f6.json. Report an issue: GitHub ↗.