elastic/elasticsearch · error · UserException
74
74
Error message
bin dir for {pluginId} is not a directory What it means
Thrown by RemovePluginAction.checkCanRemove when a plugin's bin directory exists at env.binDir().resolve(pluginId) but is not a directory (i.e. it is a regular file or special node). Exit code IO_ERROR (74). This guards removePlugin from trying to treat a non-directory path as a directory.
Source
Thrown at distribution/tools/plugin-cli/src/main/java/org/elasticsearch/plugins/cli/RemovePluginAction.java:153
if (PLUGINS_CONVERTED_TO_MODULES.contains(pluginId)) {
terminal.errorPrintln(
"plugin [" + pluginId + "] is no longer a plugin but instead a module packaged with this distribution of Elasticsearch"
);
} else {
final String message = String.format(
Locale.ROOT,
"plugin [%s] not found; run 'elasticsearch-plugin list' to get list of installed plugins",
pluginId
);
throw new UserException(ExitCodes.CONFIG, message);
}
}
final Path pluginBinDir = env.binDir().resolve(pluginId);
if (Files.exists(pluginBinDir)) {
if (Files.isDirectory(pluginBinDir) == false) {
throw new UserException(ExitCodes.IO_ERROR, "bin dir for " + pluginId + " is not a directory");
}
}
}
private void removePlugin(InstallablePlugin plugin) throws IOException {
final String pluginId = plugin.getId();
final Path pluginDir = env.pluginsDir().resolve(pluginId);
final Path pluginConfigDir = env.configDir().resolve(pluginId);
final Path removing = env.pluginsDir().resolve(".removing-" + pluginId);
terminal.println("-> removing [" + pluginId + "]...");
final List<Path> pluginPaths = new ArrayList<>();
/*
* Add the contents of the plugin directory before creating the marker file and adding it to the list of paths to be deleted so
* that the marker file is the last file to be deleted.
*/View on GitHub (pinned to db6a809a66)
Solutions
- Inspect `<ES_HOME>/bin/<pluginId>`: if it is a regular file, move/remove it so the path is either absent or a directory.
- Reinstall the plugin cleanly to recreate the proper bin directory, then remove via the CLI.
- Avoid manual file creation under the bin root; use the CLI for all install/remove operations.
Example fix
# before: <ES_HOME>/bin/analysis-icu is a file ls -ld <ES_HOME>/bin/analysis-icu # remove the stray file: rm <ES_HOME>/bin/analysis-icu # then retry: bin/elasticsearch-plugin remove analysis-icu
Defensive patterns
Strategy: validation
Validate before calling
// Check the plugin bin path is a directory before removal.
Path binDir = env.binDir().resolve(id);
if (Files.exists(binDir) && !Files.isDirectory(binDir)) {
throw new IllegalStateException(binDir + " is not a directory; investigate manually");
} Prevention
- Never create files manually under ES_HOME/bin; use the CLI only.
- Audit bin/ for stray files after any manual plugin operation.
- Reinstall the affected plugin cleanly if the bin path is corrupted.
When it happens
Trigger: After the not-found check, the code resolves pluginBinDir; if `Files.exists(pluginBinDir)` is true but `Files.isDirectory(pluginBinDir)` is false, it throws. Reached when something created a regular file at `<binDir>/<pluginId>` where a directory was expected.
Common situations: A stray file (log, tarball fragment, symlink to a file) was left at the plugin's bin path; manual cleanup that `touch`ed the path; filesystem corruption or a bad extraction leaving a file where the directory should be.
Related errors
AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12).
Data as JSON: /api/errors/a882edf3ce1dce81.
Report an issue: GitHub.