quarkusio/quarkus · error · InternalServerErrorException
'state' query parameter is not equal to the q_post_logout co
Error message
'state' query parameter is not equal to the q_post_logout cookie value
What it means
The post-logout 'state' query parameter must equal the value stored in the q_post_logout_tenant-logout cookie set during the logout redirect. A mismatch indicates the callback state cannot be trusted — it may belong to a different logout session or be forged — so the endpoint rejects it.
Source
Thrown at integration-tests/oidc-code-flow/src/main/java/io/quarkus/it/keycloak/TenantLogout.java:51
@GET
@Authenticated
@Path("logout")
public String getTenantLogoutPath() {
throw new InternalServerErrorException();
}
@GET
@Path("post-logout")
public String postLogout(@QueryParam("state") String postLogoutState) {
Cookie cookie = headers.getCookies().get("q_post_logout_tenant-logout");
if (cookie == null) {
throw new InternalServerErrorException("q_post_logout cookie is not available");
}
if (postLogoutState == null) {
throw new InternalServerErrorException("'state' query parameter is not available");
}
if (!postLogoutState.equals(cookie.getValue())) {
throw new InternalServerErrorException("'state' query parameter is not equal to the q_post_logout cookie value");
}
return "You were logged out, please login again";
}
}
View on GitHub (pinned to e1c734241f)
Solutions
- Clear stale q_post_logout cookies and restart the logout flow from the beginning
- Verify only one logout flow is in flight per browser profile
- Check that the provider echoes back the exact state Quarkus issued (correct post_logout_redirect_uri and client config)
Example fix
// before
if (!postLogoutState.equals(cookie.getValue())) {
throw new InternalServerErrorException("'state' query parameter is not equal to the q_post_logout cookie value");
}
// after
if (!postLogoutState.equals(cookie.getValue())) {
return "post-logout state mismatch; please log in and log out again";
} Defensive patterns
Strategy: validation
Validate before calling
Cookie cookie = headers.getCookies().get("q_post_logout_tenant-logout");
String state = uriInfo.getQueryParameters().getFirst("state");
if (cookie != null && state != null && !state.equals(cookie.getValue())) {
// state/cookie mismatch: clear cookies and restart logout flow
} Try / catch
try {
given().get("/tenant-logout/post-logout?state=...");
} catch (InternalServerErrorException e) {
if (e.getMessage().contains("not equal to the q_post_logout")) {
// stale or forged state; clear cookies and re-login
}
} Prevention
- Clear stale q_post_logout cookies between logout attempts
- Avoid concurrent logout flows in the same browser profile
- Verify the provider echoes the exact issued state
When it happens
Trigger: The state query parameter differs from the cookie value: stale cookie from a previous logout, provider echoed an old/other state, or the request was crafted with an arbitrary state.
Common situations: Multiple logout attempts leaving a stale cookie; cookie overwritten by a concurrent session in the same browser; provider misconfiguration sending its own state format.
Related errors
- Back-channel logout path cannot contain a wildcard '*' chara
- OIDC tenants '%s' and '%s' share the same back-channel logou
- q_post_logout cookie is not available
- 'state' query parameter is not available
- Failed to generate key id
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/29f15cf261b85e56.
Report an issue: GitHub.