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
- 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.
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
- 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).
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
- Failed to create URI: {buf}
- NULL value for template parameter: {param}
- path param {param} has not been provided by the parameter ma
- values parameter is null
- You did not supply enough values to fill path parameters
AI-assisted analysis of keycloak/keycloak@66c7e15a37 (2026-08-14).
Data as JSON: /api/errors/345994581ca766f4.
Report an issue: GitHub.