{"record":{"id":"108bdcb9d2f0fd08","repo":"actualbudget/actual","slug":"no-valid-payee-ids-provided-in-ids-provide-comm","errorCode":null,"errorMessage":"No valid payee IDs provided in --ids. Provide comma-separated IDs.","messagePattern":"No valid payee IDs provided in --ids\\. Provide comma-separated IDs\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/cli/src/commands/payees.ts","lineNumber":105,"sourceCode":"          await api.deletePayee(id);\n          printOutput({ success: true, id }, opts.format);\n        },\n        { mutates: true },\n      );\n    });\n\n  payees\n    .command('merge')\n    .description('Merge payees into a target payee')\n    .requiredOption('--target <id>', 'Target payee ID')\n    .requiredOption('--ids <ids>', 'Comma-separated payee IDs to merge')\n    .action(async (cmdOpts: { target: string; ids: string }) => {\n      const mergeIds = cmdOpts.ids\n        .split(',')\n        .map(id => id.trim())\n        .filter(id => id.length > 0);\n      if (mergeIds.length === 0) {\n        throw new Error(\n          'No valid payee IDs provided in --ids. Provide comma-separated IDs.',\n        );\n      }\n      const opts = program.opts();\n      await withConnection(\n        opts,\n        async () => {\n          await api.mergePayees(cmdOpts.target, mergeIds);\n          printOutput({ success: true }, opts.format);\n        },\n        { mutates: true },\n      );\n    });\n}\n","sourceCodeStart":87,"sourceCodeEnd":120,"githubUrl":"https://github.com/actualbudget/actual/blob/d4334cb6e6123f4d3bcea1ad6166608884c7e658/packages/cli/src/commands/payees.ts#L87-L120","documentation":"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.","triggerScenarios":"Running `payees merge --target <id>` without `--ids`; passing `--ids \"\"`; passing `--ids \",,,\"` or only whitespace like `--ids \" , \"` so every entry is filtered out.","commonSituations":"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).","solutions":["Pass a comma-separated list of payee IDs, e.g. `--ids id1,id2,id3`.","Check that the source producing the ID list (script, grep, previous command) actually returned duplicates before invoking merge.","Quote the flag value so shells do not swallow commas or whitespace unexpectedly."],"exampleFix":"// before\n$ actual-cli payees merge --target t1 --ids \"$DUPES\"   # DUPES empty\n// after\n$ actual-cli payees merge --target t1 --ids \"aaa-bbb,ccc-ddd\"","handlingStrategy":"validation","validationCode":"const ids = rawIds.split(',').map(s => s.trim()).filter(Boolean);\nif (ids.length === 0) {\n  throw new Error('merge requires at least one payee id in --ids');\n}","typeGuard":null,"tryCatchPattern":"try {\n  await cli(['payees', 'merge', '--target', target, '--ids', idsArg]);\n} catch (e) {\n  if (e.message.includes('No valid payee IDs')) {\n    console.error('--ids must contain at least one non-empty, comma-separated id');\n  }\n}","preventionTips":["Build the --ids list programmatically with .filter(Boolean) before joining.","Verify the dedup source actually produced duplicate IDs before merging.","Quote the flag value in shell scripts to avoid word-splitting surprises."],"tags":["cli","validation","missing-argument"],"backgroundTag":"missing-required-argument","analyzedSha":"d4334cb6e6123f4d3bcea1ad6166608884c7e658","analyzedAt":"2026-08-29T01:02:11.213Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}