You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
When arguments() argument is provided, unrecognized flags are silently deleted (no error prints) #561
I am using commander 2.9.0 (graceful-readlink 1.0.1) on node v4.4.7 (on Windows, running in MSYS2, if it matters).
I run the following test program:
var commander = require("commander")
commander
.version("0.0.1")
.option('-x, --x-flag', 'A flag')
.arguments("<file>")
.parse(process.argv)
if (commander.xFlag)
console.log("Got -x")
console.log("Args:", commander.args)
I find that if I do not supply the <file> argument, if I pass a nonsense flag like --nonsense, I will get a nice error message. If I do supply the <file> argument, then any nonsense flags included will be silently discarded. Moreover, commander appears to assume each nonsense flag takes one option-argument, and it silently discards that, too. These flags are not appended to commander.args or anything. They just disappear.
Expected behavior: A --flag which is not recognized should result in commander printing an error.
This is a pretty bad bug. Not only does commander allow something which should be an error, and not only does it do it inconsistently for the same script depending on input, but since commander does this totally silently I cannot even write my own recovery code. If the lost arguments had been appended to commander.args at least I could detect it and raise my own error.
Reacted by Alexander Kachkaev, Matthew Walker and SlurpTheo
changed the title [-]When arguments() argument is provided, unrecognized flags are silently deleted (no error)[/-][+]When arguments() argument is provided, unrecognized flags are silently deleted (no error prints)[/+]on Aug 21, 2016
@mcclure have you found a workaround for this? I agree that not throwing when invalid arguments or options are given can be very dangerous. It's so easy to just type a wrong command and accidentally delete something important!
I'll add that I just got bitten by this today, spending a while debugging my code only to find my command line inputs were wrong. Expected valid option was --concurrency, but I fatfingered it as --condurrency, and because I also had provided an expected argument at the end, everything went forward as if all inputs were valid.
Just for the sake of clarity, my invalid command line was:
My code that uses commander is something like this:
constprogram=require('commander')program.usage('[options] <file>').arguments('<file>').option('-c, --concurrency <number>','Max number of concurrent users.',parseInt).option('-u, --users <number>','Max number of users.',parseInt).action(file=>{testPlanFile=file;}).parse(process.argv);
If I do not pass the argument, the invalid option --condurrency is detected and I get the appropriate error:
I think I found the place in the commander.js code that controls this, but unfortunately it seems to be deliberate (from index.js):
Command.prototype.parseArgs=function(args,unknown){varname;if(args.length){name=args[0];if(this.listeners(name).length){this.emit(args.shift(),args,unknown);}else{this.emit('*',args);}}else{outputHelpIfNecessary(this,unknown);// If there were no args and we have unknown options,// then they are extraneous and we need to error.if(unknown.length>0){this.unknownOption(unknown[0]);}}returnthis;};
However, I'm not sure which use case this should really be valid for.
By this point in the code, the unknown argument contains the --condurrency (invalid) option, and the args array contains the correct args passed to the program.
Also, this implementation changes behavior depending on whether or not args is populated, rather than on the rules specified by the programmer. If args contains data, then ignore unknown options. I should think unknown options would handled the same regardless of whether args were passed.
As an experiment, I changed the code to:
Command.prototype.parseArgs=function(args,unknown){varname;if(args.length){name=args[0];if(this.listeners(name).length){this.emit(args.shift(),args,unknown);}else{this.emit('*',args);}}else{outputHelpIfNecessary(this,unknown);}// Handle unknown options whether or not args are passed.if(unknown.length>0){this.unknownOption(unknown[0]);}returnthis;};
This had the desired effect (desired by me anyway ;)): Both of the following command lines produced a useful error message:
I'd love to submit a pull request to fix this, but I don't know enough about the rest of the project (at the moment) to know whether I'm on the right track, or missing something important.
@vanesyan @abetomo you two appear to be the last two to commit code to this library. I would really like to have this fixed and would be willing to send a PR. Any feedback on this before I make a PR?
In my case the command works without any options being passed but when i try to pass a option it gives me this error 😕 This is my code: program.command('edit <fileURL> <key> <value>') .description("Will edit a json file.") .option('-s, --spaces <number>', "Number of spaces to re-parse the file with.") .action((url, key, value, cmd) => {
Had a script passing accidentally -arg <argVal> <someVal> instead of --arg <argVal> <someVal>.
// test.tsimport*ascommanderfrom"commander";constfn=(opt: string)=>(a: string)=>console.log(`in ${opt}${a ? ` -- got: '${a}'` : ""}`);commander.option("-a, --abc <arg>","Pass me a value",fn("abc")).option("-x","Dummy x",fn("x")).option("-y","Dummy y",fn("y")).parse(process.argv);
Fine/good:
$ node test --help
Usage: test [options]
Options:
-a, --abc <arg> Pass me a value
-x Dummy x
-y Dummy y
-h, --help output usage information
$ node test -xy -y --abc ./test.js
in x
in y
in y
in abc -- got: './test.js'
$ node test -xy -y --abc ./test.js someVal
in x
in y
in y
in abc -- got: './test.js'
$
I guess this is okay (at least there's an error -- after my option-handling function is called with "garbage"):
$ node test -xy -y -abc ./test.js
in x
in y
in y
in abc -- got: '-b'
error: unknown option `-c'
$
But ICK!!
$ node test -xy -y -abc ./test.js someVal
in x
in y
in y
in abc -- got: '-b'
$
#965 will fix the detection of unknown options in the case the program has an action handler. The original report in this issue (#561 (comment)) does not have an action handler so won't be changed by #965.
The invalid option will get detected if the program has an action handler, even an empty one. This is a limitation due to the current implementation rather than by design.
This is actually mentioned in the README, although easily missed!
However, if an action-based command does not define an action, then the options are not validated.
Activity
[-]When arguments() argument is provided, unrecognized flags are silently deleted (no error)[/-][+]When arguments() argument is provided, unrecognized flags are silently deleted (no error prints)[/+]kachkaev commentedon Mar 3, 2017
@mcclure have you found a workaround for this? I agree that not throwing when invalid arguments or options are given can be very dangerous. It's so easy to just type a wrong command and accidentally delete something important!
matsaleh13 commentedon Apr 28, 2017
I'll add that I just got bitten by this today, spending a while debugging my code only to find my command line inputs were wrong. Expected valid option was
--concurrency, but I fatfingered it as--condurrency, and because I also had provided an expected argument at the end, everything went forward as if all inputs were valid.Just for the sake of clarity, my invalid command line was:
but it should have been:
My code that uses commander is something like this:
If I do not pass the argument, the invalid option
--condurrencyis detected and I get the appropriate error:error: unknown option `--condurrency'matsaleh13 commentedon Apr 28, 2017
I think I found the place in the
commander.jscode that controls this, but unfortunately it seems to be deliberate (fromindex.js):However, I'm not sure which use case this should really be valid for.
By this point in the code, the
unknownargument contains the--condurrency(invalid) option, and theargsarray contains the correct args passed to the program.Also, this implementation changes behavior depending on whether or not
argsis populated, rather than on the rules specified by the programmer. Ifargscontains data, then ignore unknown options. I should think unknown options would handled the same regardless of whether args were passed.As an experiment, I changed the code to:
This had the desired effect (desired by me anyway ;)): Both of the following command lines produced a useful error message:
node loadtester.js --condurrency 100 error: unknown option `--condurrency'and
node loadtester.js --condurrency 100 path_to_file error: unknown option `--condurrency'I'd love to submit a pull request to fix this, but I don't know enough about the rest of the project (at the moment) to know whether I'm on the right track, or missing something important.
Anyone care to guide me at this point?
Thanks!
charlierudolph commentedon Jul 12, 2017
@vanesyan @abetomo you two appear to be the last two to commit code to this library. I would really like to have this fixed and would be willing to send a PR. Any feedback on this before I make a PR?
kingerking commentedon Dec 14, 2018
In my case the command works without any options being passed but when i try to pass a option it gives me this error 😕 This is my code:
program.command('edit <fileURL> <key> <value>') .description("Will edit a json file.") .option('-s, --spaces <number>', "Number of spaces to re-parse the file with.") .action((url, key, value, cmd) => {shadowspawn commentedon Mar 30, 2019
This has not seen a lot of activity, but it is a clear bug, and I have reproduced it on Mac.
SlurpTheo commentedon Apr 10, 2019
Had a script passing accidentally
-arg <argVal> <someVal>instead of--arg <argVal> <someVal>.Fine/good:
I guess this is okay (at least there's an error -- after my option-handling function is called with "garbage"):
But ICK!!
shadowspawn commentedon Aug 17, 2019
#965 will fix the detection of unknown options in the case the program has an action handler. The original report in this issue (#561 (comment)) does not have an action handler so won't be changed by #965.
tageecc commentedon Dec 9, 2019
mcclure commentedon Dec 9, 2019
shadowspawn commentedon Jan 7, 2020
Opened a PR to rework option parsing to improve option parsing: #1138
Edit: #1138 only fixes some of the cases in original post, and somewhat by accident.
shadowspawn commentedon Jan 10, 2020
The invalid option will get detected if the program has an action handler, even an empty one. This is a limitation due to the current implementation rather than by design.
This is actually mentioned in the README, although easily missed!
Add back tj#561 into known issues
Add back tj#561 into known issues
Combine normalize and parseoptions, and update combined option handli…
shadowspawn commentedon Feb 1, 2020
Unknown options are reliably detected whether or not there is an action handler in the published pre-release of Commander v5.0.0 (#1163)
shadowspawn commentedon Mar 14, 2020
Commander v5.0.0 has been released with significant improvements to argument parsing.
https://github.com/tj/commander.js/releases/tag/v5.0.0