elastic/elasticsearch · error · UserException

78

78

Error message

Malformed [proxy], expected [host:port]

What it means

First of two identical-throws in ProxyUtils.buildProxy: when a non-null proxy string does not split into exactly two `:`-separated parts. buildProxy is the runtime constructor used by install/sync flows (distinct from PluginsConfig.validate, which mirrors the same rule). Exit code is CONFIG (78) via UserException.

Source

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

 * Utilities for working with HTTP proxies.
 */
class ProxyUtils {
    /**
     * Constructs a proxy from the given string. If {@code null} is passed, then {@code null} will
     * be returned, since that is not the same as {@link Proxy#NO_PROXY}.
     *
     * @param proxy the string to use, in the form "host:port"
     * @return a proxy or null
     */
    @SuppressForbidden(reason = "Proxy constructor requires a SocketAddress")
    static Proxy buildProxy(String proxy) throws UserException {
        if (proxy == null) {
            return null;
        }

        final String[] parts = proxy.split(":");
        if (parts.length != 2) {
            throw new UserException(ExitCodes.CONFIG, "Malformed [proxy], expected [host:port]");
        }

        if (validateProxy(parts[0], parts[1]) == false) {
            throw new UserException(ExitCodes.CONFIG, "Malformed [proxy], expected [host:port]");
        }

        return new Proxy(Proxy.Type.HTTP, new InetSocketAddress(parts[0], Integer.parseUnsignedInt(parts[1])));
    }

    /**
     * Check that the hostname is not empty, and that the port is numeric.
     *
     * @param hostname the hostname to check. Besides ensuring it is not null or empty, no further validation is
     *                 performed.
     * @param port the port to check. Must be composed solely of digits.
     * @return whether the arguments describe a potentially valid proxy.
     */
    static boolean validateProxy(String hostname, String port) {

View on GitHub (pinned to db6a809a66)

Solutions

  1. Pass the proxy as `host:port` only, e.g. `--proxy proxy.internal:8080`.
  2. For IPv6, use bracketed form: `[::1]:8080`.
  3. Strip any `http://`/`https://` scheme — buildProxy adds Proxy.Type.HTTP itself.

Example fix

# before:
bin/elasticsearch-plugin install x --proxy http://proxy:8080
# after:
bin/elasticsearch-plugin install x --proxy proxy:8080
Defensive patterns

Strategy: validation

Validate before calling

// Validate --proxy shape before calling buildProxy.
if (proxy != null && proxy.split(":").length != 2) {
    throw new IllegalArgumentException("--proxy must be host:port");
}

Try / catch

try {
    Proxy p = ProxyUtils.buildProxy(proxyArg);
} catch (UserException e) {
    if (e.exitCode == ExitCodes.CONFIG) {
        // surface a friendly error to the operator
        System.err.println("Invalid proxy format. Use host:port (e.g. proxy.internal:8080).");
    }
    throw e;
}

Prevention

When it happens

Trigger: buildProxy receives a non-null proxy string, splits on `:`, and throws UserException(CONFIG) when parts.length != 2. Reached when the CLI --proxy flag or another caller passes a malformed proxy to buildProxy rather than going through PluginsConfig validation first.

Common situations: User passes `--proxy host` (no port) or `--proxy http://host:port` (scheme adds colons); environment variable with a bare host; IPv6 host written without brackets.

Understand the failure class

Related errors


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