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

  1. Clear stale q_post_logout cookies and restart the logout flow from the beginning
  2. Verify only one logout flow is in flight per browser profile
  3. 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

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


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/29f15cf261b85e56. Report an issue: GitHub.