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
- Contact the plugin author to remove the native-controller declaration from the descriptor.
- If you maintain the plugin, delete the `controller`/native-controller property from plugin-descriptor.properties and rebuild.
- 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
- Do not set the controller property in plugin-descriptor.properties for distributable plugins.
- Audit plugin descriptor templates copied from system internals before publishing.
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.