{"record":{"id":"345994581ca766f4","repo":"keycloak/keycloak","slug":"failed-to-create-uri","errorCode":null,"errorMessage":"Failed to create URI: ","messagePattern":"Failed to create URI: ","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"common/src/main/java/org/keycloak/common/util/KeycloakUriBuilder.java","lineNumber":471,"sourceCode":"        return buildUriFromMap(values, false, true);\n    }\n\n    public URI buildFromEncodedMap(Map<String, ?> values) throws IllegalArgumentException {\n        if (values == null) throw new IllegalArgumentException(\"values parameter is null\");\n        return buildUriFromMap(values, true, false);\n    }\n\n    public URI buildFromMap(Map<String, ?> values, boolean encodeSlashInPath) throws IllegalArgumentException {\n        if (values == null) throw new IllegalArgumentException(\"values parameter is null\");\n        return buildUriFromMap(values, false, encodeSlashInPath);\n    }\n\n    protected URI buildUriFromMap(Map<String, ?> paramMap, boolean fromEncodedMap, boolean encodeSlash) throws IllegalArgumentException {\n        String buf = buildString(paramMap, fromEncodedMap, false, encodeSlash);\n        try {\n            return URI.create(buf);\n        } catch (Exception e) {\n            throw new RuntimeException(\"Failed to create URI: \" + buf, e);\n        }\n    }\n\n    private String buildString(Map<String, ?> paramMap, boolean fromEncodedMap, boolean isTemplate, boolean encodeSlash) {\n        for (Map.Entry<String, ? extends Object> entry : paramMap.entrySet()) {\n            if (entry.getKey() == null) throw new IllegalArgumentException(\"map key is null\");\n            if (entry.getValue() == null) throw new IllegalArgumentException(\"map value is null\");\n        }\n        StringBuffer buffer = new StringBuffer();\n\n        if (scheme != null)\n            replaceParameter(paramMap, fromEncodedMap, isTemplate, scheme, buffer, encodeSlash).append(\":\");\n        if (ssp != null) {\n            buffer.append(ssp);\n        } else if (userInfo != null || host != null || port != -1) {\n            buffer.append(\"//\");\n            if (userInfo != null) {\n                if (host == null || host.isEmpty()) throw new RuntimeException(\"empty host name, but userInfo supplied\");","sourceCodeStart":453,"sourceCodeEnd":489,"githubUrl":"https://github.com/keycloak/keycloak/blob/66c7e15a3788de7764f07dd2558275a02770e16d/common/src/main/java/org/keycloak/common/util/KeycloakUriBuilder.java#L453-L489","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["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.","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.","Sanitize/trim parameter values (strip raw spaces, newlines, control chars) before adding them to the map.","Wrap the build call in try/catch(RuntimeException) and inspect getCause() instanceof URISyntaxException to fail gracefully."],"exampleFix":"// before\nURI u = KeycloakUriBuilder.fromUri(\"https://host/p/{id}\")\n        .buildFromEncodedMap(Map.of(\"id\", \"a b\")); // raw space -> malformed\n\n// after\nURI u = KeycloakUriBuilder.fromUri(\"https://host/p/{id}\")\n        .buildFromMap(Map.of(\"id\", \"a b\")); // builder percent-encodes -> https://host/p/a%20b","handlingStrategy":"try-catch","validationCode":"// Fail fast by validating the assembled string parses before relying on it.\nString buf = KeycloakUriBuilder.fromUri(template)\n        .buildAsString(new HashMap<>(values)); // mirrors buildString output\ntry {\n    new URI(buf); // throws URISyntaxException on malformed input\n} catch (URISyntaxException e) {\n    throw new IllegalArgumentException(\"Template + values produce invalid URI: \" + buf, e);\n}","typeGuard":null,"tryCatchPattern":"try {\n    URI u = builder.buildFromMap(values);\n} catch (RuntimeException e) {\n    if (e.getCause() instanceof URISyntaxException) {\n        URISyntaxException use = (URISyntaxException) e.getCause();\n        log.warn(\"Malformed URI '{}' at index {}\", use.getInput(), use.getIndex());\n        // fall back / rethrow as domain error\n    } else {\n        throw e;\n    }\n}","preventionTips":["Prefer buildFromMap over buildFromEncodedMap unless your values are already percent-encoded.","Trim and strip control characters from externally-supplied values before adding them to the map.","Log the buf string from the message - it pinpoints the bad character.","Add a unit test that builds the URI with worst-case inputs (spaces, unicode, quotes)."],"tags":["java","keycloak","uri","uri-builder","encoding","runtime-exception"],"backgroundTag":null,"analyzedSha":"66c7e15a3788de7764f07dd2558275a02770e16d","analyzedAt":"2026-08-14T01:36:42.651Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}