elastic/elasticsearch · error · IllegalStateException

plugins can not have native controllers

Error message

plugins can not have native controllers

What it means

Thrown as a plain IllegalStateException (not a UserException, so no POSIX exit-code mapping — surfaces as an internal error / stack trace) inside loadPluginInfo when PluginDescriptor.readFromProperties reports the plugin declares a native controller. Modern Elasticsearch forbids user-installed plugins from having native controllers; only bundled system components may. This is an invariant violation by the plugin author, not a usage mistake by the operator.

Source

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

        final Path destination = pluginPath.resolve(pluginName);
        if (Files.exists(destination)) {
            final String message = String.format(
                Locale.ROOT,
                "plugin directory [%s] already exists; if you need to update the plugin, " + "uninstall it first using command 'remove %s'",
                destination,
                pluginName
            );
            throw new UserException(PLUGIN_EXISTS, message);
        }
    }

    /**
     * Load information about the plugin, and verify it can be installed with no errors.
     */
    private PluginDescriptor loadPluginInfo(Path pluginRoot) throws Exception {
        final PluginDescriptor info = PluginDescriptor.readFromProperties(pluginRoot);
        if (info.hasNativeController()) {
            throw new IllegalStateException("plugins can not have native controllers");
        }
        PluginsUtils.verifyCompatibility(info);

        // checking for existing version of the plugin
        verifyPluginName(env.pluginsDir(), info.getName());

        PluginsUtils.checkForFailedPluginRemovals(env.pluginsDir());

        terminal.println(VERBOSE, info.toString());

        // check for jar hell before any copying
        jarHellCheck(info, pluginRoot, env.pluginsDir(), env.modulesDir());

        if (info.isStable() && hasNamedComponentFile(pluginRoot) == false) {
            generateNameComponentFile(pluginRoot);
        }
        return info;
    }

View on GitHub (pinned to db6a809a66)

Solutions

  1. Contact the plugin author to remove the native-controller declaration from the descriptor.
  2. If you maintain the plugin, delete the `controller`/native-controller property from plugin-descriptor.properties and rebuild.
  3. Do not attempt to bypass — the runtime forbids native controllers for non-system plugins.

Example fix

# plugin-descriptor.properties
# before
elasticsearch.plugin.controller=true
# after
# (remove the line)
Defensive patterns

Strategy: validation

Validate before calling

Properties p = new Properties();
p.load(Files.newInputStream(Path.of(pluginDescriptorPath)));
if ("true".equalsIgnoreCase(p.getProperty("elasticsearch.plugin.controller"))) {
    throw new IllegalStateException("Plugin declares a native controller; not installable via CLI");
}

Prevention

When it happens

Trigger: A plugin descriptor file (plugin-descriptor.properties) that sets `java.controller=true` (or equivalent) and is presented for installation via the CLI.

Common situations: Third-party plugins copying properties from internal/system components; forks reusing a system plugin template that includes the controller flag.

Related errors


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