mongodb/node-mongodb-native · error · MongoInvalidArgumentError

Invalid sort direction

Error message

Invalid sort direction: ${JSON.stringify(direction)}

What it means

Thrown by the internal prepareDirection() helper when a sort direction value cannot be normalized to ascending or descending. The driver accepts 1, -1, 'asc', 'desc', 'ascending', 'descending', or a { $meta: 'textScore' } object; anything else hits the default branch of the switch and raises a MongoInvalidArgumentError. The rejected value is JSON-stringified into the message for debugging.

Solutions

  1. Ensure every sort direction value is exactly 1, -1, 'asc', 'desc', 'ascending', 'descending', or { $meta: 'textScore' }.
  2. If the direction comes from user input, map it to a valid token before passing it to .sort() (e.g. map 'up'->1, 'down'->-1).
  3. Use a type guard or validation function on the dynamic sort object before calling .sort().

Example fix

// before
const direction = req.query.order; // e.g. 'up'
collection.find().sort({ name: direction });

// after
const direction = req.query.order === 'desc' ? -1 : 1;
collection.find().sort({ name: direction });
Defensive patterns

Strategy: validation

Validate before calling

const VALID_DIRECTIONS = new Set(['1', '-1', 'asc', 'desc', 'ascending', 'descending']);
function isValidDirection(d: unknown): boolean {
  if (typeof d === 'object' && d !== null && '$meta' in d && typeof (d as any).$meta === 'string') return true;
  return typeof d === 'string' && VALID_DIRECTIONS.has(d.toLowerCase()) || d === 1 || d === -1;
}
function sanitizeSort(sort: Record<string, unknown>): Record<string, 1 | -1> {
  const out: Record<string, 1 | -1> = {};
  for (const [k, v] of Object.entries(sort)) {
    if (isValidDirection(v)) out[k] = (String(v).match(/^(1|asc|ascending)$/i) ? 1 : -1);
  }
  return out;
}

Type guard

import type { SortDirection } from 'mongodb';
function isSortDirection(v: unknown): v is SortDirection {
  if (v === 1 || v === -1) return true;
  if (typeof v === 'string') return ['asc','desc','ascending','descending'].includes(v.toLowerCase());
  if (typeof v === 'object' && v !== null && '$meta' in v && typeof (v as any).$meta === 'string') return true;
  return false;
}

Try / catch

try {
  await collection.find().sort(sortSpec).toArray();
} catch (e) {
  if (e instanceof MongoInvalidArgumentError && /Invalid sort direction/.test(e.message)) {
    // fall back to a safe default sort
    await collection.find().sort({ _id: 1 }).toArray();
  } else throw e;
}

Prevention

When it happens

Trigger: Calling collection.find().sort({ name: 'up' }) or .sort({ age: 2 }) where the direction is not one of the recognized tokens. Also triggered by .sort([['field', 'sideways']]) or passing a numeric other than 1/-1, e.g. .sort({ x: true }).

Common situations: Developers who build sort objects dynamically from user input or query parameters and pass arbitrary strings (e.g. 'up'/'down', 'high'/'low') instead of 'asc'/'desc'. Also occurs when a number like 0 or 2 is used, or when a boolean is mistakenly used as a direction.

Related errors


AI-assisted analysis of mongodb/node-mongodb-native@dce7939f86 (2026-08-11). Data as JSON: /api/errors/118e33fd673794a2. Report an issue: GitHub.

Appendix: source

Thrown at src/sort.ts:48

/** @internal */
type SortPairForCmd = [string, SortDirectionForCmd];

/** @internal */
function prepareDirection(direction: any = 1): SortDirectionForCmd {
  const value = `${direction}`.toLowerCase();
  if (isMeta(direction)) return direction;
  switch (value) {
    case 'ascending':
    case 'asc':
    case '1':
      return 1;
    case 'descending':
    case 'desc':
    case '-1':
      return -1;
    default:
      throw new MongoInvalidArgumentError(`Invalid sort direction: ${JSON.stringify(direction)}`);
  }
}

/** @internal */
function isMeta(t: SortDirection): t is { $meta: string } {
  return typeof t === 'object' && t != null && '$meta' in t && typeof t.$meta === 'string';
}

/** @internal */
function isPair(t: Sort): t is readonly [string, SortDirection] {
  if (Array.isArray(t) && t.length === 2) {
    try {
      prepareDirection(t[1]);
      return true;
    } catch {
      return false;
    }
  }

View on GitHub (pinned to dce7939f86)