elastic/elasticsearch · error · PluginSyncException

Must specify location for non-official plugin [{id}] in [ela

Error message

Must specify location for non-official plugin [{id}] in [elasticsearch-plugins.yml]

What it means

Thrown by PluginsConfig.validate for an InstallablePlugin whose id is neither in the official-plugins set nor in the migrated-plugins set, and whose location is null. Elasticsearch can only install-by-name plugins it knows about; everything else needs an explicit location (URL, file path, or Maven coordinate). It is a PluginSyncException so callers can branch on it.

Source

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

     * @throws PluginSyncException if validation problems are found
     */
    public void validate(Set<String> officialPlugins, Set<String> migratedPlugins) throws PluginSyncException {
        if (this.plugins.stream().anyMatch(each -> each == null || Strings.isNullOrBlank(each.getId()))) {
            throw new RuntimeException("Cannot have null or empty IDs in [elasticsearch-plugins.yml]");
        }

        final Set<String> uniquePluginIds = new HashSet<>();
        for (final InstallablePlugin plugin : plugins) {
            if (uniquePluginIds.add(plugin.getId()) == false) {
                throw new PluginSyncException("Duplicate plugin ID [" + plugin.getId() + "] found in [elasticsearch-plugins.yml]");
            }
        }

        for (InstallablePlugin plugin : this.plugins) {
            if (officialPlugins.contains(plugin.getId()) == false
                && migratedPlugins.contains(plugin.getId()) == false
                && plugin.getLocation() == null) {
                throw new PluginSyncException(
                    "Must specify location for non-official plugin [" + plugin.getId() + "] in [elasticsearch-plugins.yml]"
                );
            }
        }

        if (this.proxy != null) {
            final String[] parts = this.proxy.split(":");
            if (parts.length != 2) {
                throw new PluginSyncException("Malformed [proxy], expected [host:port] in [elasticsearch-plugins.yml]");
            }

            if (ProxyUtils.validateProxy(parts[0], parts[1]) == false) {
                throw new PluginSyncException("Malformed [proxy], expected [host:port] in [elasticsearch-plugins.yml]");
            }
        }

        for (InstallablePlugin p : plugins) {
            if (p.getLocation() != null) {

View on GitHub (pinned to db6a809a66)

Solutions

  1. Add a `location:` (URL, file:// path, or Maven coordinate) to the plugin entry in elasticsearch-plugins.yml.
  2. Check the plugin id spelling against the official plugins list for your ES version.
  3. If the plugin was migrated to a module, you can leave the id (migrated set) — otherwise supply location.

Example fix

# before:
plugins:
  - id: my-custom-plugin   # not official, no location
# after:
plugins:
  - id: my-custom-plugin
    location: file:///opt/plugins/my-custom-plugin.zip
Defensive patterns

Strategy: validation

Validate before calling

// Ensure every non-official, non-migrated plugin has a location.
for (InstallablePlugin p : parsed.getPlugins()) {
    if (!official.contains(p.getId()) && !migrated.contains(p.getId()) && p.getLocation() == null) {
        throw new IllegalArgumentException("Plugin " + p.getId() + " needs a location");
    }
}

Prevention

When it happens

Trigger: validate iterates the plugins list; for each plugin not recognised as official/migrated and with `plugin.getLocation() == null`, it throws. This fires before the proxy and location-format checks.

Common situations: User added a custom or third-party plugin by id only, assuming it is installable by name; typo in the id that no longer matches an official plugin; previously official plugin removed from the official set in a new ES version.

Related errors


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