elastic/elasticsearch · error · IllegalArgumentException

unable to parse URI [${uriString}]

Error message

unable to parse URI [${uriString}]

What it means

UriParts.parse first attempts new URI(uriString); if that throws URISyntaxException it falls back to new URL(uriString). Only if both fail does it raise IllegalArgumentException. So the input must be malformed for both the strict URI parser and the lenient URL parser (no valid scheme/host).

Source

Thrown at libs/web-utils/src/main/java/org/elasticsearch/web/UriParts.java:75

    public static Map<String, Object> parse(String uriString) {
        final var uriParts = new UriPartsMapCollector();
        parse(uriString, uriParts);
        return uriParts;
    }

    @SuppressForbidden(reason = "URL.getPath is used only if URI.getPath is unavailable")
    public static void parse(final String uriString, final UriPartsCollector uriPartsCollector) {
        URI uri = null;
        URL fallbackUrl = null;
        try {
            uri = new URI(uriString);
        } catch (URISyntaxException e) {
            try {
                // noinspection deprecation
                fallbackUrl = new URL(uriString);
            } catch (MalformedURLException e2) {
                throw new IllegalArgumentException("unable to parse URI [" + uriString + "]");
            }
        }

        String domain;
        String fragment;
        String path;
        int port;
        String query;
        String scheme;
        String userInfo;

        if (uri != null) {
            domain = uri.getHost();
            fragment = uri.getFragment();
            path = uri.getPath();
            port = uri.getPort();
            query = uri.getQuery();
            scheme = uri.getScheme();

View on GitHub (pinned to db6a809a66)

Solutions

  1. Prepend a default scheme when missing: if (!uri.matches("^[a-zA-Z]+:.*")) uri = "https://" + uri
  2. Validate with a regex or pre-parse before calling UriParts.parse
  3. Filter blank/non-URL rows in the ingest pipeline before this processor

Example fix

// before
UriParts.parse("example.com/path", collector); // throws
// after
String s = raw;
if (!s.matches("^[a-zA-Z][a-zA-Z0-9+.-]*:.*")) s = "https://" + s;
UriParts.parse(s, collector);
Defensive patterns

Strategy: validation

Validate before calling

String s = raw == null ? "" : raw.trim();
if (!s.matches("^[a-zA-Z][a-zA-Z0-9+.-]*:.*")) {
    s = "https://" + s;
}
try {
    UriParts.parse(s, collector);
} catch (IllegalArgumentException e) {
    // drop or mark the row as unparseable
}

Type guard

static boolean looksLikeUri(String s) {
    if (s == null || s.isBlank()) return false;
    try { new URI(s); return true; }
    catch (URISyntaxException e1) {
        try { new URL(s); return true; }
        catch (MalformedURLException e2) { return false; }
    }
}

Try / catch

try { UriParts.parse(uri, collector); }
catch (IllegalArgumentException e) { /* route to dead-letter / skip */ }

Prevention

When it happens

Trigger: Calling UriParts.parse(uriString, collector) with a string that is neither a valid URI nor a valid URL - typically missing scheme, illegal characters, or empty. Used by the URL-decomposition ingest processor path.

Common situations: A user-supplied URL missing the scheme (example.com/path instead of https://example.com/path); control characters or spaces in the URL; a field that occasionally contains non-URL text (user agents, referrer noise); pipeline processing of malformed logs.

Understand the failure class

Related errors


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