Automattic/mongoose · error · TypeError

Invalid sort() argument. Must be a string, object, array, or

Error message

Invalid sort() argument. Must be a string, object, array, or map.

What it means

Terminal guard in sort(): after the string, array, plain object, and Map branches, any remaining non-null value throws. Numbers, booleans, symbols, and functions have no branch, so the most common hit is .sort(-1), which developers read as 'sort descending' but which is just an invalid specification.

Source

Thrown at lib/query.js:3189

      sort[key] = _handleSortValue(pair[1], key);
    }
  } else if (typeof arg === 'object' && arg != null && !(arg instanceof Map)) {
    for (const key of Object.keys(arg)) {
      if (specialProperties.has(key)) {
        continue;
      }
      sort[key] = _handleSortValue(arg[key], key);
    }
  } else if (arg instanceof Map) {
    for (let key of arg.keys()) {
      key = '' + key;
      if (specialProperties.has(key)) {
        continue;
      }
      sort[key] = _handleSortValue(arg.get(key), key);
    }
  } else if (arg != null) {
    throw new TypeError('Invalid sort() argument. Must be a string, object, array, or map.');
  }

  return this;
};

/*!
 * Convert sort values
 */

function _handleSortValue(val, key) {
  if (val === 1 || val === 'asc' || val === 'ascending') {
    return 1;
  }
  if (val === -1 || val === 'desc' || val === 'descending') {
    return -1;
  }
  if (val?.$meta != null) {
    return { $meta: val.$meta };

View on GitHub (pinned to 49cdab0136)

Solutions

  1. For descending use .sort({ field: -1 }) or .sort('-field')
  2. Validate dynamic sort specs and default to a valid spec or omit sort() entirely
  3. Type sort variables as string | Record<string, 1 | -1> | Array<[string, 1 | -1]>

Example fix

// before
Model.find().sort(-1); // invalid: -1 is not a sort spec

// after
Model.find().sort({ createdAt: -1 });
// or
Model.find().sort('-createdAt');
Defensive patterns

Strategy: type-guard

Validate before calling

const ALLOWED_SORTS = { newest: { createdAt: -1 }, oldest: { createdAt: 1 } };
const spec = ALLOWED_SORTS[String(req.query.sort ?? 'newest')] ?? { createdAt: -1 };
const q = Model.find().sort(spec);

Type guard

function isSortSpec(v) {
  return v == null || typeof v === 'string' || Array.isArray(v) || v instanceof Map ||
    (typeof v === 'object' && v !== null);
}

Prevention

When it happens

Trigger: .sort(-1) or .sort(1) meaning direction; .sort(true); .sort(() => 'a'); a dynamically computed sort variable that turns out to be a number or boolean.

Common situations: Passing -1 as the whole sort expecting descending order; booleans from feature flags; untyped config values flowing into the query builder.

Related errors


AI-assisted analysis of Automattic/mongoose@49cdab0136 (2026-08-21). Data as JSON: /api/errors/a05df9d4dda7189b. Report an issue: GitHub.