actualbudget/actual · error · Error

No valid payee IDs provided in --ids. Provide comma-separate

Error message

No valid payee IDs provided in --ids. Provide comma-separated IDs.

What it means

The `payees merge` command splits the `--ids` option on commas, trims each entry, and drops empty strings. If nothing remains there are no payee IDs to merge, so the command throws this error rather than calling the merge API with an empty list.

Source

Thrown at packages/cli/src/commands/payees.ts:105

          await api.deletePayee(id);
          printOutput({ success: true, id }, opts.format);
        },
        { mutates: true },
      );
    });

  payees
    .command('merge')
    .description('Merge payees into a target payee')
    .requiredOption('--target <id>', 'Target payee ID')
    .requiredOption('--ids <ids>', 'Comma-separated payee IDs to merge')
    .action(async (cmdOpts: { target: string; ids: string }) => {
      const mergeIds = cmdOpts.ids
        .split(',')
        .map(id => id.trim())
        .filter(id => id.length > 0);
      if (mergeIds.length === 0) {
        throw new Error(
          'No valid payee IDs provided in --ids. Provide comma-separated IDs.',
        );
      }
      const opts = program.opts();
      await withConnection(
        opts,
        async () => {
          await api.mergePayees(cmdOpts.target, mergeIds);
          printOutput({ success: true }, opts.format);
        },
        { mutates: true },
      );
    });
}

View on GitHub (pinned to d4334cb6e6)

Solutions

  1. Pass a comma-separated list of payee IDs, e.g. `--ids id1,id2,id3`.
  2. Check that the source producing the ID list (script, grep, previous command) actually returned duplicates before invoking merge.
  3. Quote the flag value so shells do not swallow commas or whitespace unexpectedly.

Example fix

// before
$ actual-cli payees merge --target t1 --ids "$DUPES"   # DUPES empty
// after
$ actual-cli payees merge --target t1 --ids "aaa-bbb,ccc-ddd"
Defensive patterns

Strategy: validation

Validate before calling

const ids = rawIds.split(',').map(s => s.trim()).filter(Boolean);
if (ids.length === 0) {
  throw new Error('merge requires at least one payee id in --ids');
}

Try / catch

try {
  await cli(['payees', 'merge', '--target', target, '--ids', idsArg]);
} catch (e) {
  if (e.message.includes('No valid payee IDs')) {
    console.error('--ids must contain at least one non-empty, comma-separated id');
  }
}

Prevention

When it happens

Trigger: Running `payees merge --target <id>` without `--ids`; passing `--ids ""`; passing `--ids ",,,"` or only whitespace like `--ids " , "` so every entry is filtered out.

Common situations: Bulk-dedup scripts that build the ID list from a previous step which returned no duplicates; copy-pasting a flag with an empty shell variable (`--ids "$IDS"` where IDS is unset).

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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