elastic/elasticsearch · error · PluginSyncException

Malformed location for plugin [{id}]

Error message

Malformed location for plugin [{id}]

What it means

Thrown by PluginsConfig.validate when a plugin location is present and non-blank but cannot be parsed as a URI. The code wraps `new URI(p.getLocation())` and rethrows URISyntaxException as PluginSyncException. The comment notes Maven coordinates are also accepted (URI is lenient for those), so a genuine syntax failure means a malformed URL or path.

Source

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

                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) {
                if (p.getLocation().isBlank()) {
                    throw new PluginSyncException("Empty location for plugin [" + p.getId() + "]");
                }

                try {
                    // This also accepts Maven coordinates
                    new URI(p.getLocation());
                } catch (URISyntaxException e) {
                    throw new PluginSyncException("Malformed location for plugin [" + p.getId() + "]");
                }
            }
        }
    }

    public List<InstallablePlugin> getPlugins() {
        return plugins;
    }

    public String getProxy() {
        return proxy;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }

View on GitHub (pinned to db6a809a66)

Solutions

  1. URL-encode the location, especially spaces: `file:///opt/my%20plugins/x.zip`.
  2. Use a proper scheme (http://, https://, file://) or a valid Maven coordinate (`group:artifact:version`).
  3. Test the value parses as a URI before deploy: `python -c "import sys,urllib.parse; print(urllib.parse.quote(sys.argv[1]))"`.

Example fix

# before:
plugins:
  - id: custom-x
    location: file:///opt/my plugins/x.zip   # space breaks URI
# after:
plugins:
  - id: custom-x
    location: file:///opt/my%20plugins/x.zip
Defensive patterns

Strategy: validation

Validate before calling

// Pre-validate that each location parses as a URI.
for (InstallablePlugin p : parsed.getPlugins()) {
    String loc = p.getLocation();
    if (loc != null && !loc.isBlank()) {
        try { new URI(loc); } catch (URISyntaxException ex) {
            throw new IllegalArgumentException("Bad location for " + p.getId() + ": " + loc, ex);
        }
    }
}

Prevention

When it happens

Trigger: For each plugin with a non-blank location, `new URI(location)` is attempted; if it throws URISyntaxException (illegal characters, bad scheme, unescaped spaces), the wrapper PluginSyncException is thrown with the plugin id.

Common situations: File path with unencoded spaces (`file:///opt/my plugins/x.zip`); URL with illegal characters; missing scheme on what should be a URL; Windows path with backslashes used where a URI is required.

Understand the failure class

Related errors


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