nodejs/node · error · RuntimeError
Bad command: %s
Error message
Bad command: %s
What it means
tools/install.py run() only handles the commands 'install' and 'uninstall' (each optionally under --headers-only). Any other command string falls through every branch and raises RuntimeError('Bad command: %s').
Source
Thrown at tools/install.py:395
subdir_files(options, zoslibinc, 'include/node/zoslib/', wanted_zoslib_headers)
def run(options):
if options.headers_only:
if options.command == 'install':
headers(options, install)
return
if options.command == 'uninstall':
headers(options, uninstall)
return
else:
if options.command == 'install':
files(options, install)
return
if options.command == 'uninstall':
files(options, uninstall)
return
raise RuntimeError('Bad command: %s\n' % options.command)
def parse_options(args):
parser = argparse.ArgumentParser(
description='Install headers and binaries into filesystem')
parser.add_argument('command', choices=['install', 'uninstall'])
parser.add_argument('--dest-dir', help='custom install prefix for packagers, i.e. DESTDIR',
default=os.getcwd())
parser.add_argument('--prefix', help='custom install prefix, i.e. PREFIX',
default='/usr/local')
parser.add_argument('--headers-only', help='only install headers',
action='store_true', default=False)
parser.add_argument('--root-dir', help='the root directory of source code',
default=os.getcwd())
parser.add_argument('--build-dir', help='the location of built binaries',
default='out/Release')
parser.add_argument('--v8-dir', help='the location of V8',
default='deps/v8')
parser.add_argument('--config-gypi-path', help='the location of config.gypi',View on GitHub (pinned to 1b2de5e052)
Solutions
- Pass only 'install' or 'uninstall' as the command.
- If calling run() directly, validate options.command against {'install','uninstall'} before invoking.
- Drive the tool via its CLI (argparse already restricts choices) rather than calling run() by hand.
Example fix
// before options.command='build' # run(options) raises 'Bad command' // after options.command='install' # or 'uninstall'
Defensive patterns
Strategy: validation
Validate before calling
assert options.command in ('install','uninstall'), f'Bad command: {options.command}' Type guard
def is_valid_command(c: str) -> bool:
return c in ('install','uninstall') Prevention
- Use the CLI entry point so argparse enforces choices.
- Validate command against the allowed set before any programmatic call.
When it happens
Trigger: Calling install.py's run(options) programmatically with options.command set to something other than 'install' or 'uninstall', bypassing the argparse `choices` restriction that normally makes this unreachable from the CLI.
Common situations: A wrapper script or build-system integration that constructs options manually and passes a wrong/typo command; legacy callers from before choices were constrained.
Related errors
- No libnode.so to install!
- Environment variable ZOSLIB_INCLUDES is not set
- Cannot find out dir, did you run build?
- This script does not support running with cygwin python.
- Error: Don't know how to unpack %s with extension %s
AI-assisted analysis of nodejs/node@1b2de5e052 (2026-08-13).
Data as JSON: /api/errors/bcef824007b0bbdf.
Report an issue: GitHub.