actualbudget/actual · error · Error

Either --data or --file is required

Error message

Either --data or --file is required

What it means

readJsonInput requires a JSON source: if neither --data nor --file is provided it throws this error. The commands that consume JSON payloads (transactions import, rules, schedules, fields) cannot proceed without input, so this fails fast before any parsing or network work.

Source

Thrown at packages/cli/src/input.ts:20

export function readJsonInput(cmdOpts: {
  data?: string;
  file?: string;
}): unknown {
  if (cmdOpts.data && cmdOpts.file) {
    throw new Error('Cannot use both --data and --file');
  }
  if (cmdOpts.data) {
    return JSON.parse(cmdOpts.data);
  }
  if (cmdOpts.file) {
    const content =
      cmdOpts.file === '-'
        ? readFileSync(0, 'utf-8')
        : readFileSync(cmdOpts.file, 'utf-8');
    return JSON.parse(content);
  }
  throw new Error('Either --data or --file is required');
}

View on GitHub (pinned to d4334cb6e6)

Solutions

  1. Add --file payload.json pointing at your JSON file.
  2. Or pass the JSON inline with --data '{...}'.
  3. When piping from stdin, use --file - explicitly (e.g. cat txns.json | cmd --file -).
  4. Check in scripts that the variable holding the JSON is non-empty before invoking.

Example fix

// before
actual-cli transactions --sync-id $ID
// after
actual-cli transactions --sync-id $ID --file txns.json
Defensive patterns

Strategy: validation

Validate before calling

if (!cmdOpts.data && !cmdOpts.file) {
  throw new Error('No JSON input: provide --data, --file <path>, or --file - for stdin.');
}
if (cmdOpts.file === '-' && process.stdin.isTTY) {
  throw new Error('--file - given but nothing is piped to stdin.');
}

Type guard

function hasJsonInput(o: { data?: string; file?: string }): o is typeof o & ({ data: string } | { file: string }) {
  return Boolean(o.data || o.file);
}

Try / catch

try {
  const json = readJsonInput({ data: opts.data, file: opts.file });
} catch (err) {
  if (err instanceof Error && err.message === 'Either --data or --file is required') {
    console.error('Supply the JSON payload via --data or --file (use - for stdin).');
    process.exit(2);
  }
  throw err;
}

Prevention

When it happens

Trigger: Calling a command that needs a JSON body without --data or --file; intending to pipe stdin but forgetting that '-' must be given to --file; an empty variable expanding to nothing ($DATA unset with --data "$DATA").

Common situations: Script where the payload variable was never set; docs example where the user omitted the file argument; forgetting `--file -` when piping from another command.

Related errors


AI-assisted analysis of actualbudget/actual@d4334cb6e6 (2026-08-29). Data as JSON: /api/errors/5ea5522b70d9a8b3. Report an issue: GitHub.