{"id":"a56ba73932080ff1","repo":"tj/commander.js","slug":"only-the-last-argument-can-be-variadic-previous","errorCode":null,"errorMessage":"only the last argument can be variadic '${previousArgument.name()}'","messagePattern":"only the last argument can be variadic '(.+?)'","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"lib/command.js","lineNumber":379,"sourceCode":"    names\n      .trim()\n      .split(/ +/)\n      .forEach((detail) => {\n        this.argument(detail);\n      });\n    return this;\n  }\n\n  /**\n   * Define argument syntax for command, adding a prepared argument.\n   *\n   * @param {Argument} argument\n   * @return {Command} `this` command for chaining\n   */\n  addArgument(argument) {\n    const previousArgument = this.registeredArguments.slice(-1)[0];\n    if (previousArgument?.variadic) {\n      throw new Error(\n        `only the last argument can be variadic '${previousArgument.name()}'`,\n      );\n    }\n    if (\n      argument.required &&\n      argument.defaultValue !== undefined &&\n      argument.parseArg === undefined\n    ) {\n      throw new Error(\n        `a default value for a required argument is never used: '${argument.name()}'`,\n      );\n    }\n    this.registeredArguments.push(argument);\n    return this;\n  }\n\n  /**\n   * Customise or override default help command. By default a help command is automatically added if your command has subcommands.","sourceCodeStart":361,"sourceCodeEnd":397,"githubUrl":"https://github.com/tj/commander.js/blob/ba6d13ddb4243e5913367734f8c159089ffe7834/lib/command.js#L361-L397","documentation":"Thrown by Command.addArgument() at lib/command.js:378-382 when an argument is added after an argument that is already variadic (name ending in `...`). Variadic arguments capture all remaining positional tokens, so nothing may follow them; Commander enforces this at registration time.","triggerScenarios":"`.arguments('<files...> <dest>')`, or chained `.argument('<inputs...>').argument('<output>')`. The check looks at the last registered argument: if it is variadic, adding another throws.","commonSituations":"Trying to express 'many source files then a destination' with the variadic in the wrong slot; converting a fixed-arity signature to variadic and forgetting to reorder; misreading docs that show variadic must be last.","solutions":["Move the variadic to the end: `.arguments('<dest> <files...>')` is wrong order semantically — instead restructure to `.argument('<output>').argument('<inputs...>')` so variadic is last.","If you need 'sources... then dest', require dest as an option (`.option('-o, --out <path>')`) instead of a positional, then keep `<files...>` as the sole variadic positional.","Split into two commands or use a delimiter the user passes."],"exampleFix":"// before (throws: variadic not last)\n.arguments('<files...> <dest>')\n\n// after (variadic last, dest as option)\n.argument('<files...>')\n.option('-o, --out <dest>', 'destination')","handlingStrategy":"validation","validationCode":"// Ensure variadic is last when building args dynamically\nfunction addArgsSafe(cmd, specs) {\n  const lastVariadicIdx = specs.findIndex(s => s.endsWith('...'));\n  if (lastVariadicIdx !== -1 && lastVariadicIdx !== specs.length - 1) {\n    throw new Error('variadic argument must be the last one');\n  }\n  specs.forEach(s => cmd.argument(s));\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Place variadic arguments last by convention; review .arguments() strings carefully.","Prefer options for trailing required tokens (e.g. -o/--out) when the variadic must come first semantically.","Lint .arguments() calls in review."],"tags":["commander","argument","variadic","configuration"],"analyzedSha":"ba6d13ddb4243e5913367734f8c159089ffe7834","analyzedAt":"2026-08-03T20:26:04.326Z","schemaVersion":2}