elastic/elasticsearch · error · UserException

64

64

Error message

at least one plugin id is required

What it means

Thrown by `InstallPluginAction.execute(List<InstallablePlugin>)` when the plugins list is empty. Exits USAGE (64). This is the programmatic entry point (the CLI parsing layer builds the list from positional args before calling execute), so hitting it directly means a caller invoked execute with no plugins. The check runs before uniqueness validation and before any download.

Source

Thrown at distribution/tools/plugin-cli/src/main/java/org/elasticsearch/plugins/cli/InstallPluginAction.java:209

    private final Terminal terminal;
    private Environment env;
    private boolean batch;
    private Proxy proxy = null;

    public InstallPluginAction(Terminal terminal, Environment env, boolean batch) {
        this.terminal = terminal;
        this.env = env;
        this.batch = batch;
    }

    public void setProxy(Proxy proxy) {
        this.proxy = proxy;
    }

    public void execute(List<InstallablePlugin> plugins) throws Exception {
        if (plugins.isEmpty()) {
            throw new UserException(ExitCodes.USAGE, "at least one plugin id is required");
        }

        final Set<String> uniquePluginIds = new HashSet<>();
        for (final InstallablePlugin plugin : plugins) {
            if (uniquePluginIds.add(plugin.getId()) == false) {
                throw new UserException(ExitCodes.USAGE, "duplicate plugin id [" + plugin.getId() + "]");
            }
        }

        final String logPrefix = terminal.isHeadless() ? "" : "-> ";

        final Map<String, List<Path>> deleteOnFailures = new LinkedHashMap<>();
        for (final InstallablePlugin plugin : plugins) {
            final String pluginId = plugin.getId();
            terminal.println(logPrefix + "Installing " + pluginId);
            try {
                if ("x-pack".equals(pluginId)) {
                    throw new UserException(ExitCodes.CONFIG, "this distribution of Elasticsearch contains X-Pack by default");

View on GitHub (pinned to db6a809a66)

Solutions

  1. Pass at least one InstallablePlugin in the list when calling execute.
  2. Guard callers: `if (!plugins.isEmpty()) action.execute(plugins);`.
  3. At the CLI level, ensure at least one plugin id positional arg is supplied.

Example fix

// before
action.execute(List.of());
// after
action.execute(List.of(new InstallablePlugin.Id("repository-s3")));
Defensive patterns

Strategy: validation

Validate before calling

if (plugins == null || plugins.isEmpty()) {
    throw new IllegalArgumentException("InstallPluginAction.execute requires at least one plugin");
}

Prevention

When it happens

Trigger: Calling `new InstallPluginAction(...).execute(emptyList())` directly; a CLI/wrapper that resolves plugin ids from config and resolves to none; misrouted invocation that dropped its args.

Common situations: Programmatic automation that conditionally installs plugins and the condition yielded an empty list; a custom CLI built on top of InstallPluginAction.

Related errors


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