{"record":{"id":"4f76067733c6fbc6","repo":"actualbudget/actual","slug":"invalid-order-direction","errorCode":null,"errorMessage":"Invalid order direction: ","messagePattern":"Invalid order direction: ","errorType":"exception","errorClass":"CompileError","httpStatus":null,"severity":"error","filePath":"packages/loot-core/src/server/aql/compiler.ts","lineNumber":975,"sourceCode":"    } else {\n      const entries = Object.entries(expr);\n      const entry = entries[0];\n\n      // Check if this is a field reference\n      if (entries.length === 1 && entry[0][0] !== '$') {\n        dir = entry[1];\n        compiled = compileExpr(state, '$' + entry[0]).value;\n      } else {\n        // Otherwise it's a function\n        const { $dir, ...func } = expr;\n        dir = $dir;\n        compiled = compileFunction(state, func).value;\n      }\n    }\n\n    if (dir != null) {\n      if (dir !== 'desc' && dir !== 'asc') {\n        throw new CompileError('Invalid order direction: ' + dir);\n      }\n      return `${compiled} ${dir}`;\n    }\n    return compiled;\n  });\n\n  return orderBy.join(', ');\n});\n\nconst AGGREGATE_FUNCTIONS = ['$sum', '$count'];\nfunction isAggregateFunction(expr) {\n  if (typeof expr !== 'object' || Array.isArray(expr)) {\n    return false;\n  }\n\n  const [name, originalArgExprs] = Object.entries(expr)[0];\n  let argExprs = originalArgExprs;\n  if (!Array.isArray(argExprs)) {","sourceCodeStart":957,"sourceCodeEnd":993,"githubUrl":"https://github.com/actualbudget/actual/blob/d4334cb6e6123f4d3bcea1ad6166608884c7e658/packages/loot-core/src/server/aql/compiler.ts#L957-L993","documentation":"compileOrderBy validates the optional direction suffix of an order spec; it only accepts the exact strings 'desc' and 'asc'. Any other value (including empty-ish or misspelled strings) throws this CompileError.","triggerScenarios":"Calling `.orderBy('date', 'DESC')` (uppercase), `.orderBy('date', 'descending')`, or passing an invalid dynamic variable as the direction argument.","commonSituations":"Uppercase SQL-style direction keywords, user-supplied sort direction from UI state that wasn't normalized, or passing `null`/undefined strings from config.","solutions":["Lowercase the direction string before passing: `dir.toLowerCase()` and ensure it is exactly 'asc' or 'desc'.","Normalize user/config-driven sort order with a whitelist mapping to 'asc'/'desc'.","Omit the direction argument entirely to use the default ascending order."],"exampleFix":"// before\n.orderBy('date', 'DESC')\n// after\n.orderBy('date', 'desc')","handlingStrategy":"validation","validationCode":"function normalizeDir(dir) {\n  if (dir == null) return undefined;\n  const d = String(dir).toLowerCase();\n  if (d !== 'asc' && d !== 'desc') throw new Error(`Invalid order direction: ${dir}`);\n  return d;\n}","typeGuard":"const isSortDir = (v) => v === 'asc' || v === 'desc';","tryCatchPattern":null,"preventionTips":["Normalize UI/config sort input with toLowerCase() before passing.","Type sort direction as the union 'asc' | 'desc' end to end.","Never pass user-supplied strings directly as order direction."],"tags":["aql","query-compiler","invalid-argument"],"backgroundTag":"invalid-order-direction","analyzedSha":"d4334cb6e6123f4d3bcea1ad6166608884c7e658","analyzedAt":"2026-08-29T01:02:11.213Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}