{"record":{"id":"6be7ea497ff35149","repo":"Automattic/mongoose","slug":"invalid-sort-argument-must-be-array-of-arrays","errorCode":null,"errorMessage":"Invalid sort() argument, must be array of arrays","messagePattern":"Invalid sort\\(\\) argument, must be array of arrays","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"lib/query.js","lineNumber":3165,"sourceCode":"    this.options.sort = {};\n  }\n  const sort = this.options.sort;\n  if (typeof arg === 'string') {\n    const properties = arg.indexOf(' ') === -1 ? [arg] : arg.split(' ');\n    for (let property of properties) {\n      const ascend = '-' == property[0] ? -1 : 1;\n      if (ascend === -1) {\n        property = property.slice(1);\n      }\n      if (specialProperties.has(property)) {\n        continue;\n      }\n      sort[property] = ascend;\n    }\n  } else if (Array.isArray(arg)) {\n    for (const pair of arg) {\n      if (!Array.isArray(pair)) {\n        throw new TypeError('Invalid sort() argument, must be array of arrays');\n      }\n      const key = '' + pair[0];\n      if (specialProperties.has(key)) {\n        continue;\n      }\n      sort[key] = _handleSortValue(pair[1], key);\n    }\n  } else if (typeof arg === 'object' && arg != null && !(arg instanceof Map)) {\n    for (const key of Object.keys(arg)) {\n      if (specialProperties.has(key)) {\n        continue;\n      }\n      sort[key] = _handleSortValue(arg[key], key);\n    }\n  } else if (arg instanceof Map) {\n    for (let key of arg.keys()) {\n      key = '' + key;\n      if (specialProperties.has(key)) {","sourceCodeStart":3147,"sourceCodeEnd":3183,"githubUrl":"https://github.com/Automattic/mongoose/blob/49cdab01366679723b487ecb754b38570f783289/lib/query.js#L3147-L3183","documentation":"When sort() receives an array, every element must itself be a [key, direction] pair. A flat array such as .sort(['name', -1]) — a single pair wrapped once instead of twice — or a mixed array like [['a', 1], 'b'] fails this TypeError inside the array branch of sort().","triggerScenarios":".sort(['name', -1]) (most common: wrapping the pair in one array); .sort([['a', 1], 'b']); dynamically building pairs and pushing bare strings among arrays.","commonSituations":"Converting Sequelize's order: [['field', 'DESC']] or TypeORM orderBy arrays but wrapping incorrectly; spreading a single field/direction pair into the array; untested dynamic sort builders.","solutions":["Wrap each pair: .sort([['name', -1]])","Or use the object form: .sort({ name: -1 })","When building dynamically, always push arrays: pairs.push([field, dir])"],"exampleFix":"// before\nModel.find().sort(['createdAt', -1]);\n\n// after\nModel.find().sort([['createdAt', -1]]);\n// or\nModel.find().sort({ createdAt: -1 });","handlingStrategy":"type-guard","validationCode":"// Ensure a dynamically built sort array only contains [key, dir] pairs\nfunction toSortPairs(entries) {\n  return entries\n    .filter(e => Array.isArray(e) && typeof e[0] === 'string')\n    .map(([field, dir]) => [field, dir === -1 || String(dir).startsWith('d') ? -1 : 1]);\n}\nconst q = Model.find().sort(toSortPairs(sortInput));","typeGuard":"const isSortPairArray = (v) => Array.isArray(v) && v.every(p => Array.isArray(p));","tryCatchPattern":null,"preventionTips":["Wrap every pair twice when using array syntax: [['field', -1]]","Validate ORM-ported order arrays before passing them to sort()","Prefer object specs for single-field sorts"],"tags":["mongoose","query","sort","typeerror","invalid-argument"],"backgroundTag":"invalid-sort-argument","analyzedSha":"49cdab01366679723b487ecb754b38570f783289","analyzedAt":"2026-08-21T22:54:00.882Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}