keycloak/keycloak · error · RuntimeException

Failed to create URI:

Error message

Failed to create URI: 

What it means

Thrown by buildUriFromMap after buildString assembles the URI text and URI.create(buf) fails with a URISyntaxException. It is an unchecked RuntimeException (unlike the IllegalArgumentException guards elsewhere) that re-throws the original cause and echoes the offending buf string. The map-based build path (buildFromMap / buildFromEncodedMap / buildFromMap(map, encodeSlashInPath)) is the only route here. The assembled string violates RFC 2396 so the JDK refuses to parse it.

Source

Thrown at common/src/main/java/org/keycloak/common/util/KeycloakUriBuilder.java:471

        return buildUriFromMap(values, false, true);
    }

    public URI buildFromEncodedMap(Map<String, ?> values) throws IllegalArgumentException {
        if (values == null) throw new IllegalArgumentException("values parameter is null");
        return buildUriFromMap(values, true, false);
    }

    public URI buildFromMap(Map<String, ?> values, boolean encodeSlashInPath) throws IllegalArgumentException {
        if (values == null) throw new IllegalArgumentException("values parameter is null");
        return buildUriFromMap(values, false, encodeSlashInPath);
    }

    protected URI buildUriFromMap(Map<String, ?> paramMap, boolean fromEncodedMap, boolean encodeSlash) throws IllegalArgumentException {
        String buf = buildString(paramMap, fromEncodedMap, false, encodeSlash);
        try {
            return URI.create(buf);
        } catch (Exception e) {
            throw new RuntimeException("Failed to create URI: " + buf, e);
        }
    }

    private String buildString(Map<String, ?> paramMap, boolean fromEncodedMap, boolean isTemplate, boolean encodeSlash) {
        for (Map.Entry<String, ? extends Object> entry : paramMap.entrySet()) {
            if (entry.getKey() == null) throw new IllegalArgumentException("map key is null");
            if (entry.getValue() == null) throw new IllegalArgumentException("map value is null");
        }
        StringBuffer buffer = new StringBuffer();

        if (scheme != null)
            replaceParameter(paramMap, fromEncodedMap, isTemplate, scheme, buffer, encodeSlash).append(":");
        if (ssp != null) {
            buffer.append(ssp);
        } else if (userInfo != null || host != null || port != -1) {
            buffer.append("//");
            if (userInfo != null) {
                if (host == null || host.isEmpty()) throw new RuntimeException("empty host name, but userInfo supplied");

View on GitHub (pinned to 66c7e15a37)

Solutions

  1. Read the buf value printed in the message to see exactly which character URI.create rejected, and check the wrapped URISyntaxException.getIndex() for the position.
  2. If you used buildFromEncodedMap, switch to buildFromMap so the builder percent-encodes the values, OR pre-encode every value yourself before putting it in the map.
  3. Sanitize/trim parameter values (strip raw spaces, newlines, control chars) before adding them to the map.
  4. Wrap the build call in try/catch(RuntimeException) and inspect getCause() instanceof URISyntaxException to fail gracefully.

Example fix

// before
URI u = KeycloakUriBuilder.fromUri("https://host/p/{id}")
        .buildFromEncodedMap(Map.of("id", "a b")); // raw space -> malformed

// after
URI u = KeycloakUriBuilder.fromUri("https://host/p/{id}")
        .buildFromMap(Map.of("id", "a b")); // builder percent-encodes -> https://host/p/a%20b
Defensive patterns

Strategy: try-catch

Validate before calling

// Fail fast by validating the assembled string parses before relying on it.
String buf = KeycloakUriBuilder.fromUri(template)
        .buildAsString(new HashMap<>(values)); // mirrors buildString output
try {
    new URI(buf); // throws URISyntaxException on malformed input
} catch (URISyntaxException e) {
    throw new IllegalArgumentException("Template + values produce invalid URI: " + buf, e);
}

Try / catch

try {
    URI u = builder.buildFromMap(values);
} catch (RuntimeException e) {
    if (e.getCause() instanceof URISyntaxException) {
        URISyntaxException use = (URISyntaxException) e.getCause();
        log.warn("Malformed URI '{}' at index {}", use.getInput(), use.getIndex());
        // fall back / rethrow as domain error
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: Calling buildFromMap or buildFromEncodedMap with a parameter value that produces an unparseable URI string: a raw space in an already-encoded map (buildFromEncodedMap skips re-encoding), a value containing characters Encode does not cover, a malformed scheme/host assembled from template substitution, or a userInfo set with no host (which produces 'empty host name' upstream).

Common situations: Misconfigured realm baseUrl/frontendUrl/adminUrl leaving literal template braces resolved to illegal characters; reverse-proxy X-Forwarded headers producing a host with spaces or upper-case illegal chars; using buildFromEncodedMap on values that were never percent-encoded; OIDC redirect_uri generation where a client-supplied segment contains a raw fragment/space.

Related errors


AI-assisted analysis of keycloak/keycloak@66c7e15a37 (2026-08-14). Data as JSON: /api/errors/345994581ca766f4. Report an issue: GitHub.