expressjs/express · warning

Status must be a number

Error message

Status must be a number

What it means

A deprecation warning (via `deprecate()`, not a throw) from `res.redirect`'s two-argument form `res.redirect(status, url)` when the first argument is not a number. Execution continues and the non-numeric status is later used to index `statuses.message[status]` and set the response code, yielding an undefined reason phrase or invalid status; older Express accepted `res.redirect(url, status)` in either order, and this warning flags that removed leniency.

Source

Thrown at lib/response.js:835

  var body;
  var status = 302;

  // allow status / url
  if (arguments.length === 2) {
    status = arguments[0]
    address = arguments[1]
  }

  if (!address) {
    deprecate('Provide a url argument');
  }

  if (typeof address !== 'string') {
    deprecate('Url must be a string');
  }

  if (typeof status !== 'number') {
    deprecate('Status must be a number');
  }

  // Set location header
  address = this.location(address).get('Location');

  // Support text/{plain,html} by default
  this.format({
    text: function(){
      body = statuses.message[status] + '. Redirecting to ' + address
    },

    html: function(){
      var u = escapeHtml(address);
      body = '<!DOCTYPE html><head><title>' + statuses.message[status] + '</title></head>'
       + '<body><p>' + statuses.message[status] + '. Redirecting to ' + u + '</p></body>'
    },

    default: function(){

View on GitHub ↗ (pinned to a3714473fe)

Solutions

  1. Use the correct order with a numeric status: `res.redirect(301, '/login')`.
  2. Coerce string statuses to numbers first: `res.redirect(Number(status), url)`.
  3. If you just want a default redirect, drop the status entirely — `res.redirect(url)` uses 302.

Example fix

// before
res.redirect('/login', 301);
// after
res.redirect(301, '/login');
Defensive patterns

Strategy: type-guard

Validate before calling

const status = Number(rawStatus);
if (!Number.isInteger(status) || status < 300 || status > 399) {
  return res.redirect(302, target); // sane default redirect status
}
res.redirect(status, target);

Type guard

function isRedirectStatus(s) {
  return Number.isInteger(s) && s >= 300 && s <= 399;
}

Prevention

When it happens

Trigger: `res.redirect('/login', 301)` (Express 3-era reversed argument order), `res.redirect('301', url)` with the status as a string, or a status pulled from config/env that arrives as a string.

Common situations: Legacy code migrated from Express 3 where `res.redirect(url, status)` was allowed; status codes read from environment variables or JSON that are strings; passing `err.status` that was set to a string.

Related errors


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