NationalSecurityAgency/ghidra · error · IllegalArgumentException

Unsupported command: {}

Error message

Unsupported command: {}

What it means

Thrown inside readOptions() when ALLOWED_OPTION_MAP.get(command) returns null. Because run() already validated the command against COMMAND_SET before calling readOptions(), and all 18 registered commands have entries in ALLOWED_OPTION_MAP, this is a defensive guard that indicates a programming bug: a developer registered a new command via defineCommand() but forgot to add its entry to ALLOWED_OPTION_MAP in the static initializer.

Source

Thrown at Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/query/ingest/BSimLaunchable.java:296

		else if (ghidraURLString != null) {
			bsimURL = BSimClientFactory.deriveBSimURL(ghidraURLString);
		}
	}

	/**
	 * Read in any optional parameters, strip them from the parameter stream
	 * @param command command name
	 * @param params is the original array of command line parameters
	 * @param discard number of params already consumed
	 * @return an array of parameters with optional ones stripped
	 */
	private List<String> readOptions(String command, String[] params, int discard) {

		boolean sawOptions = false;

		Set<String> allowedParams = ALLOWED_OPTION_MAP.get(command);
		if (allowedParams == null) {
			throw new IllegalArgumentException("Unsupported command: " + command);
		}

		List<String> subParams = new ArrayList<String>();
		for (int i = discard; i < params.length; ++i) {
			String optionName = params[i];
			String value = null;

			if (optionName.startsWith("-")) {
				// although not prefered, allow option value to be specified as --option=value
				int ix = optionName.indexOf("=");
				if (ix > 1) {
					value = optionName.substring(ix + 1);
					optionName = optionName.substring(0, ix);
				}
			}

			String option = optionName;

View on GitHub (pinned to d5f144c24d)

Solutions

  1. Add the new command's option set to ALLOWED_OPTION_MAP in the static initializer block (around line 170).
  2. Ensure defineCommand() and the ALLOWED_OPTION_MAP.put() call are both present for any new command.
  3. Add an integration test that runs the command through BSimLaunchable.run() to catch the missing entry.

Example fix

// before: command registered but not in ALLOWED_OPTION_MAP
private static final String COMMAND_NEW_CMD = defineCommand("newcmd");
// ...
static {
    ALLOWED_OPTION_MAP.put(COMMAND_CREATE_DATABASE, CREATE_DATABASE_OPTIONS);
    // COMMAND_NEW_CMD missing!
}

// after
private static final Set<String> NEW_CMD_OPTIONS = Set.of(NAME_OPTION);
static {
    ALLOWED_OPTION_MAP.put(COMMAND_NEW_CMD, NEW_CMD_OPTIONS);
Defensive patterns

Strategy: validation

Validate before calling

if (!ALLOWED_OPTION_MAP.containsKey(command)) {
    throw new IllegalStateException(
        "Programming bug: command '" + command + "' is registered in COMMAND_SET " +
        "but missing from ALLOWED_OPTION_MAP");
}

Prevention

When it happens

Trigger: A new BSim command is added to COMMAND_SET via defineCommand() but the developer omits the corresponding ALLOWED_OPTION_MAP.put(...) in the static block at lines 170-187. A user running that new command hits this before any work begins.

Common situations: Contributing a new BSim subcommand to Ghidra; the code compiles and passes unit tests that don't exercise the full CLI path, but the integration test or manual CLI run fails.

Related errors


AI-assisted analysis of NationalSecurityAgency/ghidra@d5f144c24d (2026-08-14). Data as JSON: /api/errors/343dab46bbb56702. Report an issue: GitHub.