{"record":{"id":"6c6c7304beb41b7a","repo":"actualbudget/actual","slug":"cannot-use-both-data-and-file","errorCode":null,"errorMessage":"Cannot use both --data and --file","messagePattern":"Cannot use both --data and --file","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/cli/src/input.ts","lineNumber":8,"sourceCode":"import { readFileSync } from 'fs';\n\nexport function readJsonInput(cmdOpts: {\n  data?: string;\n  file?: string;\n}): unknown {\n  if (cmdOpts.data && cmdOpts.file) {\n    throw new Error('Cannot use both --data and --file');\n  }\n  if (cmdOpts.data) {\n    return JSON.parse(cmdOpts.data);\n  }\n  if (cmdOpts.file) {\n    const content =\n      cmdOpts.file === '-'\n        ? readFileSync(0, 'utf-8')\n        : readFileSync(cmdOpts.file, 'utf-8');\n    return JSON.parse(content);\n  }\n  throw new Error('Either --data or --file is required');\n}\n","sourceCodeStart":1,"sourceCodeEnd":22,"githubUrl":"https://github.com/actualbudget/actual/blob/d4334cb6e6123f4d3bcea1ad6166608884c7e658/packages/cli/src/input.ts#L1-L22","documentation":"readJsonInput accepts JSON payload from either an inline --data string or a --file path (with '-' meaning stdin). Supplying both is ambiguous, so it throws immediately before reading anything. This is a mutual-exclusion guard on the command's input options.","triggerScenarios":"A command invocation that includes both --data '{...}' and --file payload.json; scripts where a wrapper adds --data while the user also passes --file.","commonSituations":"Shell scripts accumulating flags across conditionals; copy-pasting an example command that already contains --data onto one that uses --file; CI templates with default data plus user-provided file.","solutions":["Remove --data and keep --file (or vice versa) in the invocation.","If building the command in a script, make the branches mutually exclusive (if/else) rather than appending both flags.","Use --file - with piped stdin instead of embedding large JSON in --data."],"exampleFix":"// before\nactual-cli transactions --sync-id $ID --data '[...]' --file txns.json\n// after\nactual-cli transactions --sync-id $ID --file txns.json","handlingStrategy":"validation","validationCode":"const sources = [cmdOpts.data, cmdOpts.file].filter(Boolean);\nif (sources.length > 1) throw new Error('Pass either --data or --file, not both.');\nif (sources.length === 0) throw new Error('Pass --data or --file (- for stdin).');","typeGuard":null,"tryCatchPattern":"try {\n  const json = readJsonInput({ data: opts.data, file: opts.file });\n} catch (err) {\n  if (err instanceof Error && err.message === 'Cannot use both --data and --file') {\n    console.error('Choose one input source: --data or --file.');\n    process.exit(2);\n  }\n  throw err;\n}","preventionTips":["In wrapper scripts, build flags with if/else so data/file are mutually exclusive.","Standardize on --file - with stdin for programmatic pipelines.","Document one canonical input method per integration.","Add a usage check in CI scripts that greps the constructed command line for both flags."],"tags":["cli","options","input"],"backgroundTag":"conflicting-cli-options","analyzedSha":"d4334cb6e6123f4d3bcea1ad6166608884c7e658","analyzedAt":"2026-08-29T01:02:11.213Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}