{"record":{"id":"6ea0622cc8c91fd5","repo":"actualbudget/actual","slug":"table-is-required-when-the-input-file-lacks-a-t","errorCode":null,"errorMessage":"--table is required when the input file lacks a \"table\" field","messagePattern":"--table is required when the input file lacks a \"table\" field","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/cli/src/commands/query.ts","lineNumber":124,"sourceCode":"\nconst AVAILABLE_TABLES = Object.keys(TABLE_SCHEMA).join(', ');\n\nconst LAST_DEFAULT_SELECT = [\n  'date',\n  'account.name',\n  'payee.name',\n  'category.name',\n  'amount',\n  'notes',\n];\n\nfunction buildQueryFromFile(\n  parsed: Record<string, unknown>,\n  fallbackTable: string | undefined,\n) {\n  const table = typeof parsed.table === 'string' ? parsed.table : fallbackTable;\n  if (!table) {\n    throw new Error(\n      '--table is required when the input file lacks a \"table\" field',\n    );\n  }\n  let queryObj = api.q(table);\n  if (Array.isArray(parsed.select)) queryObj = queryObj.select(parsed.select);\n  if (isRecord(parsed.filter)) queryObj = queryObj.filter(parsed.filter);\n  if (Array.isArray(parsed.orderBy)) {\n    queryObj = queryObj.orderBy(parsed.orderBy);\n  }\n  if (typeof parsed.limit === 'number') queryObj = queryObj.limit(parsed.limit);\n  if (typeof parsed.offset === 'number') {\n    queryObj = queryObj.offset(parsed.offset);\n  }\n  if (Array.isArray(parsed.groupBy)) {\n    queryObj = queryObj.groupBy(parsed.groupBy);\n  }\n  return queryObj;\n}","sourceCodeStart":106,"sourceCodeEnd":142,"githubUrl":"https://github.com/actualbudget/actual/blob/d4334cb6e6123f4d3bcea1ad6166608884c7e658/packages/cli/src/commands/query.ts#L106-L142","documentation":"When `query` reads its query from a `--file`, the JSON may declare which table to query via a top-level `\"table\"` field. If the file lacks it and no `--table` fallback flag was given, `buildQueryFromFile` cannot determine the data source and throws this error.","triggerScenarios":"Running `actual query --file q.json` where q.json has `select`/`filter` but no `\"table\"` key, and the command line omits `--table`.","commonSituations":"Hand-written query files copied from examples that omitted `table`; exported query JSON from tools that store the table elsewhere; forgetting that `--file` does not imply a default table.","solutions":["Add `\"table\": \"transactions\"` (or another valid table) to the JSON file.","Or pass `--table transactions` on the command line as the fallback.","Validate the query JSON against the expected shape before invoking the CLI."],"exampleFix":"// before (q.json)\n{ \"select\": [\"date\", \"amount\"] }\n// after\n{ \"table\": \"transactions\", \"select\": [\"date\", \"amount\"] }","handlingStrategy":"validation","validationCode":"const q = JSON.parse(fs.readFileSync(file, 'utf8'));\nif (typeof q.table !== 'string' && !tableFlag) {\n  throw new Error('query file must contain a \"table\" field or pass --table');\n}","typeGuard":"function hasTable(q: unknown): q is { table: string } & Record<string, unknown> {\n  return typeof q === 'object' && q !== null && typeof (q as any).table === 'string';\n}","tryCatchPattern":"try {\n  await cli(['query', '--file', file]);\n} catch (e) {\n  if (e.message.includes('--table is required')) {\n    console.error('Add \"table\" to the query JSON or pass --table');\n  }\n}","preventionTips":["Always include a top-level \"table\" key in query files.","Validate query JSON with a schema (zod/ajv) before running.","Keep --table on the command as a fallback in scripted invocations."],"tags":["cli","validation","query","missing-field"],"backgroundTag":"missing-required-field","analyzedSha":"d4334cb6e6123f4d3bcea1ad6166608884c7e658","analyzedAt":"2026-08-29T01:02:11.213Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}