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
- Use the correct order with a numeric status: `res.redirect(301, '/login')`.
- Coerce string statuses to numbers first: `res.redirect(Number(status), url)`.
- 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
- res.redirect(status, url) requires a numeric status — config files and query strings give you strings, so coerce with Number() first
- Prefer the one-argument res.redirect(url) form (defaults to 302) unless you specifically need 301/303/307/308
- Restrict accepted values to the 3xx redirect codes you actually intend to use
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
- Provide a url argument
- Url must be a string
- Invalid status code: ${JSON.stringify(code)}. Status code mu
- name argument is required to req.get
- name must be a string to req.get
AI-assisted analysis of expressjs/express@a3714473fe (2026-07-31).
Data as JSON: /data/errors/5b7fa15a36eee5d4.json.
Report an issue: GitHub ↗.