tj/commander.js · error · Error
Unexpected value for event passed to hook : '${event}'. Expe
Error message
Unexpected value for event passed to hook : '${event}'.
Expecting one of '${allowedValues.join("', '")}' What it means
Thrown by Command.hook() at lib/command.js:490-493 when the `event` argument is not one of the supported lifecycle events: 'preSubcommand', 'preAction', or 'postAction'. Hooks are stored keyed by event in _lifeCycleHooks, so an unknown event would silently never fire — Commander fails fast instead.
Source
Thrown at lib/command.js:491
this.helpCommand(undefined, undefined); // use default name and description
}
return this._helpCommand;
}
return null;
}
/**
* Add hook for life cycle event.
*
* @param {string} event
* @param {Function} listener
* @return {Command} `this` command for chaining
*/
hook(event, listener) {
const allowedValues = ['preSubcommand', 'preAction', 'postAction'];
if (!allowedValues.includes(event)) {
throw new Error(`Unexpected value for event passed to hook : '${event}'.
Expecting one of '${allowedValues.join("', '")}'`);
}
if (this._lifeCycleHooks[event]) {
this._lifeCycleHooks[event].push(listener);
} else {
this._lifeCycleHooks[event] = [listener];
}
return this;
}
/**
* Register callback to use as replacement for calling process.exit.
*
* @param {Function} [fn] optional callback which will be passed a CommanderError, defaults to throwing
* @return {Command} `this` command for chaining
*/
exitOverride(fn) {View on GitHub (pinned to ba6d13ddb4)
Solutions
- Use one of the documented events exactly: 'preSubcommand', 'preAction', or 'postAction' (case-sensitive).
- Upgrade/downgrade to align Commander version with the event names your code assumes.
- If you need a phase Commander doesn't expose (e.g. pre-parse), use the action handler itself or wrap program.parse.
Example fix
// before (throws)
.hook('preParse', (cmd, opts) => { /* ... */ })
// after
.hook('preAction', (cmd, opts) => { /* ... */ }) Defensive patterns
Strategy: type-guard
Validate before calling
const HOOK_EVENTS = ['preSubcommand', 'preAction', 'postAction'];
function registerHook(cmd, event, fn) {
if (!HOOK_EVENTS.includes(event)) {
throw new TypeError(`hook event must be one of ${HOOK_EVENTS.join(', ')}`);
}
cmd.hook(event, fn);
} Type guard
type HookEvent = 'preSubcommand' | 'preAction' | 'postAction';
function isHookEvent(v: unknown): v is HookEvent {
return v === 'preSubcommand' || v === 'preAction' || v === 'postAction';
} Prevention
- Pin the Commander version to match the hook names your code uses.
- Drive hook registration from a typed const, not free-form strings.
- Double-check camelCase: 'preAction' not 'preaction'.
When it happens
Trigger: Calling `.hook('preParse', fn)`, `.hook('beforeAction', fn)`, or any string outside the allow-list. Typos like 'preaction' (lowercase) vs 'preAction' (camelCase) also trip it because the check is case-sensitive.
Common situations: Version skew: an older Commander version had fewer hook events and code was written against different names; copy-pasting hook names from a blog post that used non-existent events; assuming symmetric 'pre'/'post' naming for every phase.
Related errors
- 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
- Cannot add option '${option.flags}'${this._name && ` to comm
- cannot add command '${newCmd}' as already have command '${ex
AI-assisted analysis of tj/commander.js@ba6d13ddb4 (2026-08-03).
Data as JSON: /data/errors/8c21482278aa5b5b.json.
Report an issue: GitHub.