quarkusio/quarkus · error · OidcClientException
Refresh token is null
Error message
Refresh token is null
What it means
OidcClientImpl.refreshTokens() requires a non-null refresh token string because it is sent as the refresh_token grant parameter. A null argument fails fast with an OidcClientException rather than producing a broken token request.
Source
Thrown at extensions/oidc-client/runtime/src/main/java/io/quarkus/oidc/client/runtime/OidcClientImpl.java:118
this.clientSecret = clientCredentials.clientSecret;
this.clientAssertionProvider = clientCredentials.clientAssertionProvider;
}
@Override
public Uni<Tokens> getTokens(Map<String, String> additionalGrantParameters) {
checkClosed();
if (tokenGrantParams == null) {
throw new OidcClientException(
"Only 'refresh_token' grant is supported, please call OidcClient#refreshTokens method instead");
}
return getJsonResponse(OidcEndpoint.Type.TOKEN, tokenGrantParams, additionalGrantParameters, Operation.GET);
}
@Override
public Uni<Tokens> refreshTokens(String refreshToken, Map<String, String> additionalGrantParameters) {
checkClosed();
if (refreshToken == null) {
throw new OidcClientException("Refresh token is null");
}
MultiMap refreshGrantParams = copyMultiMap(commonRefreshGrantParams);
refreshGrantParams.add(OidcConstants.REFRESH_TOKEN_VALUE, refreshToken);
return getJsonResponse(OidcEndpoint.Type.TOKEN, refreshGrantParams, additionalGrantParameters, Operation.REFRESH);
}
@Override
public Uni<Boolean> revokeAccessToken(String accessToken, Map<String, String> additionalParameters) {
checkClosed();
if (accessToken == null) {
throw new OidcClientException("Access token is null");
}
OidcRequestContextProperties requestProps = getRequestProps(null);
if (tokenRevokeUri != null) {
MultiMap tokenRevokeParams = MultiMap.caseInsensitiveMultiMap();
tokenRevokeParams.set(OidcConstants.REVOCATION_TOKEN, accessToken);
return withAsyncCredentials().flatMap(asyncCredentials -> postRequest(requestProps,View on GitHub (pinned to e1c734241f)
Solutions
- Check the refresh token for null/blank before calling refreshTokens() and re-authenticate (or call getTokens()) if absent.
- Persist Tokens.refreshToken only when present and handle the absent case in your token store.
- Verify the OIDC provider actually issues refresh tokens (offline_access scope or equivalent) for the configured grant.
Example fix
// before
Tokens t = oidcClient.refreshTokens(current.getRefreshToken(), Map.of()).await().indefinitely();
// after
if (current.getRefreshToken() != null) {
Tokens t = oidcClient.refreshTokens(current.getRefreshToken(), Map.of()).await().indefinitely();
} else {
Tokens t = oidcClient.getTokens().await().indefinitely();
} Defensive patterns
Strategy: type-guard
Validate before calling
String rt = tokens.getRefreshToken();
if (rt == null || rt.isBlank()) {
throw new IllegalStateException("No refresh token available; re-authentication required");
} Type guard
boolean hasRefreshToken(Tokens t) { return t != null && t.getRefreshToken() != null && !t.getRefreshToken().isBlank(); } Try / catch
try {
return client.refreshTokens(rt, params);
} catch (OidcClientException e) {
if (e.getMessage().contains("Refresh token is null")) {
return reauthenticate();
}
throw e;
} Prevention
- Request scopes that yield refresh tokens (e.g. offline_access).
- Never persist Tokens without checking refresh token presence.
- Default to full re-authentication when no refresh token exists.
When it happens
Trigger: Calling oidcClient.refreshTokens(null, additionalGrantParameters) — typically when the stored/previous Tokens had no refresh token (e.g. the OP did not issue one) and null was propagated.
Common situations: Identity providers that omit refresh_token in responses; persisting Tokens without checking refresh token availability; code assuming a refresh token always exists.
Related errors
- Access token is null
- Extension name cannot be null
- Cannot add header, key and value must not be null
- Cannot remove header, key must not be null
- Contextual parameter must not be null
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/e33c5cf1a8cb6244.
Report an issue: GitHub.