elastic/elasticsearch · error · UserException

USAGE

USAGE

Error message

Unknown command [${subcommandName}]

What it means

Thrown by MultiCommand.execute when the first positional argument does not match any key in the configured `subcommands` map. MultiCommand is the base class for CLI tools that dispatch to subcommands (e.g. `elasticsearch-keystore`, `elasticsearch-plugin`); each subcommand registers its name, and an unknown name is a usage error. Exit code USAGE indicates the user invoked the tool wrong, not that anything is broken.

Source

Thrown at libs/cli/src/main/java/org/elasticsearch/cli/MultiCommand.java:89

        println.accept("");
    }

    @Override
    protected void execute(Terminal terminal, OptionSet options, ProcessInfo processInfo) throws Exception {
        if (subcommands.isEmpty()) {
            throw new IllegalStateException("No subcommands configured");
        }

        // .values(...) returns an unmodifiable list
        final List<String> args = new ArrayList<>(arguments.values(options));
        if (args.isEmpty()) {
            throw new MissingCommandException();
        }

        String subcommandName = args.remove(0);
        Command subcommand = subcommands.get(subcommandName);
        if (subcommand == null) {
            throw new UserException(ExitCodes.USAGE, "Unknown command [" + subcommandName + "]");
        }

        for (final KeyValuePair pair : this.settingOption.values(options)) {
            args.add("-E" + pair);
        }

        subcommand.mainWithoutErrorHandling(args.toArray(new String[0]), terminal, processInfo);
    }

    @Override
    public void close() throws IOException {
        IOUtils.close(subcommands.values());
    }

    static final class MissingCommandException extends UserException {
        MissingCommandException() {
            super(ExitCodes.USAGE, "Missing required command");
        }

View on GitHub (pinned to db6a809a66)

Solutions

  1. Run the tool with no arguments or `--help` to list valid subcommands.
  2. Correct the spelling to match a registered subcommand exactly (case-sensitive).
  3. If the subcommand should exist, verify you are on the version that introduced it.

Example fix

// before
bin/elasticsearch-plugin instal analysis-icu
// after
bin/elasticsearch-plugin install analysis-icu
// list valid subcommands
bin/elasticsearch-plugin --help
Defensive patterns

Strategy: validation

Validate before calling

Set<String> valid = cli.subcommandNames(); // expose the registered names
if (!valid.contains(requestedSub)) {
    throw new IllegalArgumentException("Unknown subcommand " + requestedSub + "; valid: " + valid);
}

Type guard

static boolean isKnownSubcommand(MultiCommand cli, String name) {
    return cli.getSubcommands().containsKey(name);
}

Try / catch

try {
    cli.main(args);
} catch (UserException e) {
    if (e.exitCode == ExitCodes.USAGE && e.getMessage().startsWith("Unknown command")) {
        // print help with the registered subcommands and exit
    } else throw e;
}

Prevention

When it happens

Trigger: Typing `elasticsearch-plugin instal x-pack` instead of `install`. Using a subcommand name from a different version. Forgetting the subcommand entirely so the first token is parsed as a subcommand name.

Common situations: Auto-complete typo. Copy-pasting a command from docs for a different version. Misremembering verb forms (e.g. `list` vs `ls`).

Related errors


AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12). Data as JSON: /api/errors/27f89d2e4e1a2a69. Report an issue: GitHub.