keycloak/keycloak · error · VerificationException
Token not set
Error message
Token not set
What it means
Thrown by TokenVerifier.parse() when both the jws field and the tokenString field are null. parse() needs a token to deserialize; if no token string was supplied to the verifier (and no pre-parsed JWSInput), there is nothing to parse. This is a usage error — the verifier was constructed without a token and then asked to parse.
Source
Thrown at core/src/main/java/org/keycloak/TokenVerifier.java:402
audienceChecks[i] = new AudienceCheck(expectedAudiences[i]);
}
return this.replaceCheck(AudienceCheck.class, true, audienceChecks);
}
/**
* Add check for verifying that token issuedFor (azp claim) is the expected value
*
* @param expectedIssuedFor issuedFor, which needs to be in the target token. Can't be null
* @return This token verifier
*/
public TokenVerifier<T> issuedFor(String expectedIssuedFor) {
return this.replaceCheck(IssuedForCheck.class, true, new IssuedForCheck(expectedIssuedFor));
}
public TokenVerifier<T> parse() throws VerificationException {
if (jws == null) {
if (tokenString == null) {
throw new VerificationException("Token not set");
}
try {
jws = new JWSInput(tokenString);
} catch (JWSInputException e) {
throw new VerificationException("Failed to parse JWT", e);
}
try {
token = jws.readJsonContent(clazz);
} catch (JWSInputException e) {
throw new VerificationException("Failed to read access token from JWT", e);
}
}
return this;
}
View on GitHub (pinned to 66c7e15a37)
Solutions
- Ensure a non-null token string is supplied to TokenVerifier.create(token, clazz) before calling parse/verify.
- Add a null/empty guard on the extracted Authorization header before constructing the verifier.
- If the token is optional in your flow, branch before building the verifier rather than letting parse() throw.
Example fix
// before: header may be null, verifier built unconditionally
TokenVerifier.create(header, AccessToken.class).verify();
// after: guard the token source
if (header == null || header.isBlank()) {
throw new UnauthorizedException("Missing bearer token");
}
TokenVerifier.create(header, AccessToken.class).verify(); Defensive patterns
Strategy: validation
Validate before calling
// Guard the token source before constructing the verifier
if (tokenString == null || tokenString.isBlank()) {
throw new UnauthorizedException("Missing bearer token");
}
TokenVerifier.create(tokenString, AccessToken.class).verify(); Type guard
static boolean hasToken(String s) {
return s != null && !s.isBlank();
} Try / catch
try {
TokenVerifier.create(token, AccessToken.class).verify();
} catch (VerificationException e) {
if (e.getMessage().equals("Token not set")) {
// caller error — no token provided; return 401
} else throw e;
} Prevention
- Always null/blank-check the Authorization header before building a verifier.
- Construct the verifier only in the branch where a token is known to exist.
- Return 401 early for missing tokens rather than relying on parse() to throw.
When it happens
Trigger: Calling TokenVerifier.create(null, AccessToken.class) (or constructing a verifier and never setting a token) followed by .parse() or .verify(). The jws==null branch is entered and the inner tokenString==null check trips.
Common situations: A code path that extracts a token from a request header but proceeds even when the header is absent, or building a verifier lazily and forgetting to populate the token string.
Related errors
- Subject missing in token
- Token is not active
- Realm URL not set
- Invalid token issuer. Expected '...'
- Token type is incorrect. Expected '...' but was '...'
AI-assisted analysis of keycloak/keycloak@66c7e15a37 (2026-08-14).
Data as JSON: /api/errors/c957d38df9d26030.
Report an issue: GitHub.