elastic/elasticsearch · error · UserException
64
64
Error message
Plugins config [{pluginsConfig}] exists, which is used by Elasticsearch on startup to ensure the correct plugins are installed. Instead of using this tool, you need to update this config file and restart Elasticsearch. What it means
Thrown by SyncPluginsAction.ensureNoConfigFile when elasticsearch-plugins.yml exists in env.configDir(). Its presence means plugin management is delegated to the sync flow on startup, so the manual install/remove tooling refuses to run. Exit code USAGE (64). The message tells the user to edit the config and restart instead.
Source
Thrown at distribution/tools/plugin-cli/src/main/java/org/elasticsearch/plugins/cli/SyncPluginsAction.java:66
public static final String ELASTICSEARCH_PLUGINS_YML_CACHE = ".elasticsearch-plugins.yml.cache";
private final Terminal terminal;
private final Environment env;
public SyncPluginsAction(Terminal terminal, Environment env) {
this.terminal = terminal;
this.env = env;
}
/**
* Ensures that the plugin config file does <b>not</b> exist.
* @param env the environment to check
* @throws UserException if a plugins config file is found.
*/
public static void ensureNoConfigFile(Environment env) throws UserException {
final Path pluginsConfig = env.configDir().resolve(ELASTICSEARCH_PLUGINS_YML);
if (Files.exists(pluginsConfig)) {
throw new UserException(
ExitCodes.USAGE,
"Plugins config ["
+ pluginsConfig
+ "] exists, which is used by Elasticsearch on startup to ensure the correct plugins "
+ "are installed. Instead of using this tool, you need to update this config file and restart Elasticsearch."
);
}
}
/**
* Synchronises plugins from the config file to the plugins dir.
*
* @throws Exception if anything goes wrong
*/
public void execute() throws Exception {
final Path configPath = this.env.configDir().resolve(ELASTICSEARCH_PLUGINS_YML);
final Path previousConfigPath = this.env.pluginsDir().resolve(ELASTICSEARCH_PLUGINS_YML_CACHE);
View on GitHub (pinned to db6a809a66)
Solutions
- Edit elasticsearch-plugins.yml to add/remove the plugin entry, then restart Elasticsearch so SyncPluginsAction reconciles.
- If you want to use the manual CLI, remove or rename elasticsearch-plugins.yml first.
- Pick one plugin-management mode (declarative via yml OR manual CLI) and stay consistent.
Example fix
# before: elasticsearch-plugins.yml present, manual CLI blocked
bin/elasticsearch-plugin install x # throws
# after (declarative mode):
# edit <config>/elasticsearch-plugins.yml to add `x`, then:
systemctl restart elasticsearch
# or (manual mode): remove the yml first
mv <config>/elasticsearch-plugins.yml{,.bak}
bin/elasticsearch-plugin install x Defensive patterns
Strategy: validation
Validate before calling
// Detect declarative mode before invoking manual install/remove.
Path yml = env.configDir().resolve("elasticsearch-plugins.yml");
if (Files.exists(yml)) {
throw new IllegalStateException("Declarative plugins config present at " + yml + " — edit it and restart instead");
} Try / catch
try {
installAction.execute(...);
} catch (UserException e) {
if (e.exitCode == ExitCodes.USAGE && e.getMessage().contains("Plugins config")) {
System.err.println("This node uses elasticsearch-plugins.yml. Edit it and restart.");
}
throw e;
} Prevention
- Choose one plugin management mode (declarative yml OR manual CLI) per cluster.
- In runbooks, branch on the presence of elasticsearch-plugins.yml before documenting CLI steps.
- CI-test both modes separately so operators do not mix them.
When it happens
Trigger: The install/remove CLI calls ensureNoConfigFile(env) before doing work; if `env.configDir().resolve(ELASTICSEARCH_PLUGINS_YML)` exists, UserException(USAGE) is thrown immediately. This prevents the manual and sync flows from racing on plugin state.
Common situations: Operator set up declarative plugin management (elasticsearch-plugins.yml) and then tried to run `elasticsearch-plugin install/remove` manually; leftover config file from a previous managed setup.
Related errors
AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12).
Data as JSON: /api/errors/a5930e10c64a3c19.
Report an issue: GitHub.