elastic/elasticsearch · error · PluginSyncException
Failed to list existing plugins
Error message
Failed to list existing plugins
What it means
Thrown when an IOException occurs while listing installed plugins via Files.newDirectoryStream(env.pluginsDir()) or reading a plugin's descriptor properties. The sync action wraps any I/O failure in PluginSyncException so the caller (SyncPluginsCliProvider) can surface it as a CONFIG error.
Source
Thrown at distribution/tools/plugin-cli/src/main/java/org/elasticsearch/plugins/cli/SyncPluginsAction.java:296
plugins.add(info);
// Check for a version mismatch, unless it's an official plugin since we can upgrade them.
if (InstallPluginAction.OFFICIAL_PLUGINS.contains(info.getName())
&& info.getElasticsearchVersion().toString().equals(Build.current().version()) == false) {
this.terminal.errorPrintln(
String.format(
Locale.ROOT,
"WARNING: plugin [%s] was built for Elasticsearch version %s but version %s is required",
info.getName(),
info.getElasticsearchVersion(),
Build.current().version()
)
);
}
}
}
} catch (IOException e) {
throw new PluginSyncException("Failed to list existing plugins", e);
}
return plugins;
}
/**
* Returns a list of all elements in {@code left} that are not present in {@code right}.
* <p>
* Comparisons are based solely using {@link InstallablePlugin#getId()}.
*
* @param left the items that may be retained
* @param right the items that may be removed
* @return a list of the remaining elements
*/
private static List<InstallablePlugin> difference(List<InstallablePlugin> left, List<InstallablePlugin> right) {
return left.stream().filter(eachDescriptor -> {
final String id = eachDescriptor.getId();
return right.stream().anyMatch(p -> p.getId().equals(id)) == false;View on GitHub (pinned to db6a809a66)
Solutions
- Check the caused-by IOException in the stack trace for the exact path that failed.
- ls -la $ES_HOME/plugins/* and confirm each plugin dir is readable by the ES user and contains plugin-descriptor.properties.
- Remove and reinstall the offending plugin via elasticsearch-plugin install <name>.
- Fix filesystem permissions: chown -R elasticsearch:elasticsearch $ES_HOME/plugins.
Defensive patterns
Strategy: try-catch
Validate before calling
for (Path p : env.pluginsDir().toFile().listFiles()) {
Path desc = p.toPath().resolve("plugin-descriptor.properties");
if (Files.notExists(desc) || Files.isReadable(desc) == false) {
// skip or report before invoking sync
}
} Try / catch
try {
action.execute();
} catch (PluginSyncException e) {
// SyncPluginsCliProvider already wraps this; log caused-by IOException for the failing path.
throw new RuntimeException("Plugin sync failed: " + e.getMessage(), e);
} Prevention
- Keep plugins/ owned by and readable for the ES user.
- Avoid partial plugin installs — always install/remove via elasticsearch-plugin CLI.
- Periodically audit each plugin dir has a valid plugin-descriptor.properties.
When it happens
Trigger: A plugin subdirectory under plugins/ is unreadable (permissions), a plugin descriptor .properties file is missing/corrupt, or the directory stream hits an I/O error (NFS hiccup, broken symlink, SELinux denial).
Common situations: Partial plugin install left a half-extracted .zip; plugin dir owned by root but ES runs as a different user; NFS/network mount flakiness; manually copied a plugin without its plugin-descriptor.properties.
Related errors
- Failed to create parent directory '%s' when creating directo
- Failed to create directory '%s'
- Plugins directory missing: {pluginsDir}
- Failed to list entitlement jars in: ${dir}
- could not remove the following files (in the order of attemp
AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12).
Data as JSON: /api/errors/8794f061e366698f.
Report an issue: GitHub.