keycloak/keycloak · error · VerificationException
Realm URL not set
Error message
Realm URL not set
What it means
Thrown by RealmUrlCheck.test when the predicate was constructed with a null realmUrl. RealmUrlCheck validates that the token's issuer matches the expected realm URL; if no expected URL was supplied there is nothing to compare against, so the check fails immediately rather than silently passing. This is a configuration/usage error in the verifier, not a property of the token.
Source
Thrown at core/src/main/java/org/keycloak/TokenVerifier.java:110
return true;
}
};
public static class RealmUrlCheck implements Predicate<JsonWebToken> {
private static final RealmUrlCheck NULL_INSTANCE = new RealmUrlCheck(null);
private final String realmUrl;
public RealmUrlCheck(String realmUrl) {
this.realmUrl = realmUrl;
}
@Override
public boolean test(JsonWebToken t) throws VerificationException {
if (this.realmUrl == null) {
throw new VerificationException("Realm URL not set");
}
if (! this.realmUrl.equals(t.getIssuer())) {
throw new VerificationException("Invalid token issuer. Expected '" + this.realmUrl + "'");
}
return true;
}
}
public static class TokenTypeCheck implements Predicate<JsonWebToken> {
private static final TokenTypeCheck INSTANCE_DEFAULT_TOKEN_TYPE = new TokenTypeCheck(Arrays.asList(TokenUtil.TOKEN_TYPE_BEARER));
private final List<String> tokenTypes;
public TokenTypeCheck(List<String> tokenTypes) {
this.tokenTypes = tokenTypes;View on GitHub (pinned to 66c7e15a37)
Solutions
- Provide a non-null realm URL to the verifier: TokenVerifier.create(...).realmUrl(issuer).verify().
- If you intentionally do not want issuer checking, remove RealmUrlCheck from the chain (use withChecks(...) without it) or pass RealmUrlCheck.NULL_INSTANCE where the API expects a check.
- Validate that the configuration source supplying the realm URL is populated before building the verifier.
Example fix
// before: realmUrl resolves to null from config
TokenVerifier.create(token, AccessToken.class)
.realmUrl(config.get("issuerUrl")) // null!
.verify();
// after: guard config, or omit the check
String issuer = config.get("issuerUrl");
TokenVerifier<T> v = TokenVerifier.create(token, AccessToken.class);
if (issuer != null) v.realmUrl(issuer);
v.verify(); Defensive patterns
Strategy: validation
Validate before calling
// Ensure a non-null realm URL before applying the check
String issuer = config.get("realmIssuerUrl");
if (issuer == null) {
// either fail configuration or skip the RealmUrlCheck entirely
throw new IllegalStateException("realmIssuerUrl not configured");
}
TokenVerifier.create(token, AccessToken.class).realmUrl(issuer).verify(); Type guard
static boolean hasRealmUrl(TokenVerifier.RealmUrlCheck c) {
// reflectively or by construction: only non-null realmUrl is usable
return c != null && c != TokenVerifier.RealmUrlCheck.NULL_INSTANCE;
} Try / catch
try {
verifier.realmUrl(realmUrl).verify();
} catch (VerificationException e) {
if (e.getMessage().equals("Realm URL not set")) {
// configuration bug — populate the issuer URL and retry
} else throw e;
} Prevention
- Always set a concrete realm URL when issuer checking is desired.
- Use RealmUrlCheck.NULL_INSTANCE or omit the check to disable it cleanly — never pass null.
- Fail fast at startup if required config keys are absent.
When it happens
Trigger: Constructing new TokenVerifier.RealmUrlCheck(null) explicitly, or calling TokenVerifier.realmUrl(null) / not setting a realmUrl while the RealmUrlCheck remains in the predicate chain. The NULL_INSTANCE constant is reserved for disabling the check and must be used instead of passing null if you intend to skip it.
Common situations: A resource server that builds its verifier dynamically and forgets to set the realm URL from configuration, or code that constructs RealmUrlCheck with a config value that resolved to null.
Related errors
- Invalid token issuer. Expected '...'
- Missing expectedAudience
- Missing expectedIssuedFor
- Subject missing in token
- Token is not active
AI-assisted analysis of keycloak/keycloak@66c7e15a37 (2026-08-14).
Data as JSON: /api/errors/f4b6273642a9f175.
Report an issue: GitHub.