{"record":{"id":"537b37a99277f8c3","repo":"actualbudget/actual","slug":"where-and-filter-are-mutually-exclusive","errorCode":null,"errorMessage":"--where and --filter are mutually exclusive","messagePattern":"--where and --filter are mutually exclusive","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/cli/src/commands/query.ts","lineNumber":172,"sourceCode":"    if (cmdOpts.limit) {\n      throw new Error('--last and --limit are mutually exclusive');\n    }\n  }\n\n  const table =\n    cmdOpts.table ?? (last !== undefined ? 'transactions' : undefined);\n  if (!table) {\n    throw new Error('--table is required (or use --file or --last)');\n  }\n\n  if (!(table in TABLE_SCHEMA)) {\n    throw new Error(\n      `Unknown table \"${table}\". Available tables: ${AVAILABLE_TABLES}`,\n    );\n  }\n\n  if (cmdOpts.where && cmdOpts.filter) {\n    throw new Error('--where and --filter are mutually exclusive');\n  }\n\n  if (cmdOpts.count && cmdOpts.select) {\n    throw new Error('--count and --select are mutually exclusive');\n  }\n\n  let queryObj = api.q(table);\n\n  if (cmdOpts.count) {\n    queryObj = queryObj.calculate({ $count: '*' });\n  } else if (cmdOpts.select) {\n    queryObj = queryObj.select(cmdOpts.select.split(','));\n  } else if (last !== undefined) {\n    queryObj = queryObj.select(LAST_DEFAULT_SELECT);\n  }\n\n  const filterStr = cmdOpts.filter ?? cmdOpts.where;\n  if (filterStr) {","sourceCodeStart":154,"sourceCodeEnd":190,"githubUrl":"https://github.com/actualbudget/actual/blob/d4334cb6e6123f4d3bcea1ad6166608884c7e658/packages/cli/src/commands/query.ts#L154-L190","documentation":"The Actual CLI's `actual query` command lets you build an AQL query either inline with --where/--select flags or via a structured --filter expression. These two filtering mechanisms are mutually exclusive, so buildQueryFromFlags throws when both --where and --filter are supplied on the same invocation. It is an early validation guard before any query is executed against the budget.","triggerScenarios":"Running `actual query transactions --where 'amount>0' --filter '{\"date\":{\"$gte\":\"2024-01-01\"}}'` — both flags set on the same command. Also happens in scripts that pass flags conditionally (e.g. a wrapper always appends --filter while the user also passes --where).","commonSituations":"Users combining examples from different docs pages; shell scripts accumulating flags from multiple config sources; copy-pasting a filter expression into an existing command that already had a --where clause.","solutions":["Remove the --where flag and express the condition inside --filter, or vice versa","Convert the --where expression into the equivalent AQL filter JSON: e.g. --where 'amount>0' becomes --filter '{\"amount\":{\"$gt\":0}}'","If a wrapper script sets --filter, drop your manual --where or edit the wrapper"],"exampleFix":"// before\nactual query transactions --where \"amount>0\" --filter '{\"date\":{\"$gte\":\"2024-01-01\"}}'\n\n// after (merge into one filter)\nactual query transactions --filter '{\"$and\":[{\"amount\":{\"$gt\":0}},{\"date\":{\"$gte\":\"2024-01-01\"}}]}'","handlingStrategy":"validation","validationCode":"// in the script that assembles CLI args\nconst args = ['query', 'transactions'];\nif (whereExpr) args.push('--where', whereExpr);\nif (filterJson) args.push('--filter', filterJson);\nif (whereExpr && filterJson) {\n  throw new Error('Pass either --where or --filter, not both');\n}","typeGuard":"function hasExclusiveFlags(opts: { where?: string; filter?: string }): boolean {\n  return opts.where !== undefined && opts.filter !== undefined;\n}","tryCatchPattern":"try {\n  await run(['actual', 'query', 'transactions', ...flags]);\n} catch (e) {\n  if (String(e.message).includes('mutually exclusive')) {\n    console.error('Drop either --where or --filter');\n  } else throw e;\n}","preventionTips":["Pick one filtering style (--filter for structured AQL, --where for quick expressions) and standardize scripts on it","Keep flag assembly in one helper so conflicting flags can't accumulate","Wrap --filter JSON in '$and' when merging conditions instead of adding --where"],"tags":["cli","aql","invalid-flags","mutually-exclusive-options"],"backgroundTag":"mutually-exclusive-cli-options","analyzedSha":"d4334cb6e6123f4d3bcea1ad6166608884c7e658","analyzedAt":"2026-08-29T01:02:11.213Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}