expressjs/express · warning

Url must be a string

Error message

Url must be a string

What it means

A deprecation warning (via `deprecate()`, not a throw) from `res.redirect` when the url argument is truthy but not a string (number, object, URL instance, array). The value is then passed to `res.location` → `encodeUrl`, which coerces it to a string, often producing a nonsensical Location header like `[object Object]`; a future major version will reject non-strings outright.

Source

Thrown at lib/response.js:831

 */

res.redirect = function redirect(url) {
  var address = url;
  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>'

View on GitHub ↗ (pinned to a3714473fe)

Solutions

  1. Convert to a string before redirecting: `res.redirect(url.href)` or `res.redirect(String(target))` when the value is a URL object.
  2. Check the two-argument form's order: `res.redirect(status, url)` — status first, url second.
  3. Validate request-derived targets are strings (repeat query params become arrays) and reject otherwise.

Example fix

// before
const target = new URL('/dashboard', baseUrl);
res.redirect(target);
// after
const target = new URL('/dashboard', baseUrl);
res.redirect(target.href);
Defensive patterns

Strategy: type-guard

Validate before calling

if (typeof target !== 'string') {
  return res.status(400).send('Bad redirect target');
}
res.redirect(target);

Type guard

function isUrlString(u) {
  return typeof u === 'string' && u.length > 0;
}

Prevention

When it happens

Trigger: `res.redirect(new URL('https://example.com'))`, `res.redirect({ path: '/home' })`, `res.redirect(301)` when the second (url) argument was forgotten so the number is treated as the url, or an array-valued query param used as the target.

Common situations: Passing WHATWG URL objects without calling `.toString()`/`.href`; swapped argument order in the two-argument form; redirect targets from JSON config or req.query arriving as objects/arrays.

Related errors


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