actualbudget/actual · error · Error

Invalid cutoff date: expected a valid date (e.g. YYYY-MM-DD)

Error message

Invalid cutoff date: expected a valid date (e.g. YYYY-MM-DD).

What it means

The accounts `transactions` (or similar) command accepts --cutoff as a date. It parses with new Date() and rejects values that produce NaN time — i.e. anything not a parseable date like YYYY-MM-DD. The guard catches malformed dates such as '2024-13-45' or '31/02/2024'.

Source

Thrown at packages/cli/src/commands/accounts.ts:168

        opts,
        async () => {
          await api.deleteAccount(id);
          printOutput({ success: true, id }, opts.format);
        },
        { mutates: true },
      );
    });

  accounts
    .command('balance <id>')
    .description('Get account balance')
    .option('--cutoff <date>', 'Cutoff date (YYYY-MM-DD)')
    .action(async (id: string, cmdOpts) => {
      let cutoff: Date | undefined;
      if (cmdOpts.cutoff) {
        const cutoffDate = new Date(cmdOpts.cutoff);
        if (Number.isNaN(cutoffDate.getTime())) {
          throw new Error(
            'Invalid cutoff date: expected a valid date (e.g. YYYY-MM-DD).',
          );
        }
        cutoff = cutoffDate;
      }
      const opts = program.opts();
      await withConnection(
        opts,
        async () => {
          const balance = await api.getAccountBalance(id, cutoff);
          printOutput({ id, balance }, opts.format);
        },
        { mutates: false },
      );
    });
}

View on GitHub (pinned to d4334cb6e6)

Solutions

  1. Pass an ISO date: --cutoff 2024-06-30.
  2. Generate the date programmatically: $(date -I) or $(date +%F) in shell.
  3. Validate the date in the calling script before invoking the CLI.
  4. If a full ISO timestamp is desired, it also parses — but prefer plain YYYY-MM-DD for consistency.

Example fix

// before
actual accounts transactions acct_1 --cutoff 30/06/2024
// after
actual accounts transactions acct_1 --cutoff "$(date -d '30 days ago' +%F)"
Defensive patterns

Strategy: validation

Validate before calling

function isValidIsoDate(s: string): boolean {
  return /^\d{4}-\d{2}-\d{2}$/.test(s) && !Number.isNaN(new Date(s + 'T00:00:00Z').getTime());
}
if (!isValidIsoDate(cutoffArg)) throw new Error(`Bad --cutoff: ${cutoffArg}`);

Type guard

function isIsoDateString(v: unknown): v is string {
  return typeof v === 'string' && /^\d{4}-\d{2}-\d{2}$/.test(v) && !Number.isNaN(new Date(v + 'T00:00:00Z').getTime());
}

Try / catch

try {
  await runCli(['accounts', 'transactions', id, '--cutoff', cutoff]);
} catch (e) {
  if (String(e.message).includes('Invalid cutoff date')) {
    console.error('Use YYYY-MM-DD, e.g. --cutoff 2024-06-30');
    process.exitCode = 2;
  } else throw e;
}

Prevention

When it happens

Trigger: Running the command with `--cutoff foo`, `--cutoff 2024-13-01`, `--cutoff 01/31/2024` in locales where that string fails to parse, or `--cutoff` followed by another flag so it received the wrong token.

Common situations: Non-ISO date formats from regional habit (DD/MM/YYYY); dates built from shell variables with wrong format; forgetting the space so --cutoff=2024-1-5 partial garbage; timezone edge strings like '2024-02-30' (invalid day).

Related errors


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