tj/commander.js · error · Error
Can not call parse again when storeOptionsAsProperties is tr
Error message
Can not call parse again when storeOptionsAsProperties is true. - either make a new Command for each call to parse, or stop storing options as properties
What it means
Thrown by Command.restoreStateBeforeParse() at lib/command.js:1171-1174 when parse() is called a second time on the same Command while storeOptionsAsProperties is true. With property-storage, option values live directly on `this` and cannot be cleanly reset across parses (the saved state only deep-restores _optionValues/_optionValueSources). Commander forbids the combo rather than risk stale or merged state.
Source
Thrown at lib/command.js:1173
this._savedState = {
// name is stable if supplied by author, but may be unspecified for root command and deduced during parsing
_name: this._name,
// option values before parse have default values (including false for negated options)
// shallow clones
_optionValues: { ...this._optionValues },
_optionValueSources: { ...this._optionValueSources },
};
}
/**
* Restore state before parse for calls after the first.
* Not usually called directly, but available for subclasses to save their custom state.
*
* This is called in a lazy way. Only commands used in parsing chain will have state restored.
*/
restoreStateBeforeParse() {
if (this._storeOptionsAsProperties)
throw new Error(`Can not call parse again when storeOptionsAsProperties is true.
- either make a new Command for each call to parse, or stop storing options as properties`);
// clear state from _prepareUserArgs
this._name = this._savedState._name;
this._scriptPath = null;
this.rawArgs = [];
// clear state from setOptionValueWithSource
this._optionValues = { ...this._savedState._optionValues };
this._optionValueSources = { ...this._savedState._optionValueSources };
// clear state from _parseCommand
this.args = [];
// clear state from _processArguments
this.processedArgs = [];
}
/**
* Throw if expected executable is missing. Add lots of help for author.
*View on GitHub (pinned to ba6d13ddb4)
Solutions
- Stop storing options as properties: `program.storeOptionsAsProperties(false)` (or just omit the call) and access via `.opts()`. Then re-parse is allowed.
- Or construct a fresh Command for each parse call.
- In tests, use beforeEach to rebuild the program rather than reusing.
Example fix
// before (throws on second parse) program.storeOptionsAsProperties(); program.parse(); program.parse(); // after (re-parse allowed, use .opts()) program.parse(); program.parse(); const opts = program.opts();
Defensive patterns
Strategy: fallback
Validate before calling
// Detect the risky combo before second parse
function assertCanReparse(cmd) {
if (cmd._storeOptionsAsProperties) {
throw new Error('Cannot re-parse with storeOptionsAsProperties=true; rebuild the Command or use .opts()');
}
} Prevention
- Default to storeOptionsAsProperties(false) and read via .opts().
- Rebuild the Command in tests via beforeEach instead of re-parsing one instance.
- Document in code comments anywhere parse() may be called more than once.
When it happens
Trigger: `program.storeOptionsAsProperties(); program.parse(); /* later */ program.parse();` — second parse hits the guard. Common in tests that parse twice, or long-lived REPL/server embedding Commander.
Common situations: Test suites reusing the program instance; interactive tools that re-parse user input; migration from Commander v4 where property storage + re-parse happened to work.
Related errors
- call .storeOptionsAsProperties() before adding options
- call .storeOptionsAsProperties() before setting option value
- Command passed to .addCommand() must have a name - specify t
- only the last argument can be variadic '${previousArgument.n
- a default value for a required argument is never used: '${ar
AI-assisted analysis of tj/commander.js@ba6d13ddb4 (2026-08-03).
Data as JSON: /data/errors/3182cf9d6090946b.json.
Report an issue: GitHub.