quarkusio/quarkus · error · InternalServerErrorException

'state' query parameter is not available

Error message

'state' query parameter is not available

What it means

The post-logout callback requires the OIDC 'state' query parameter that the provider appends when redirecting back after logout. Quarkus OIDC correlates this state with the q_post_logout cookie. A missing parameter means the callback was not produced by a genuine provider post-logout redirect.

Source

Thrown at integration-tests/oidc-code-flow/src/main/java/io/quarkus/it/keycloak/TenantLogout.java:48

    // It is needed for the proactive-auth=false to work: /tenant-logout/logout should match a user initiated logout request
    // which must be handled by `CodeAuthenticationMechanism`.
    // Adding `@Authenticated` gives control to `CodeAuthenticationMechanism` instead of RestEasy.
    @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. Complete the full logout flow so the provider redirects back with the state parameter
  2. Do not call /post-logout directly; start from the logout endpoint
  3. Check that the post-logout redirect URI given to the provider matches the endpoint exactly

Example fix

// before
if (postLogoutState == null) {
    throw new InternalServerErrorException("'state' query parameter is not available");
}
// after
if (postLogoutState == null) {
    return "state parameter missing; restart the logout flow";
}
Defensive patterns

Strategy: validation

Validate before calling

if (uriInfo.getQueryParameters().getFirst("state") == null) {
    // not a genuine provider post-logout callback; redirect to logout start
}

Try / catch

try {
    given().get("/tenant-logout/post-logout");
} catch (InternalServerErrorException e) {
    if (e.getMessage().contains("'state' query parameter")) {
        // provider did not echo state; check provider redirect config
    }
}

Prevention

When it happens

Trigger: A request reaches /tenant-logout/post-logout without the ?state=... query parameter — direct navigation, or the provider did not include state in its post-logout redirect.

Common situations: Manually bookmarking or reloading the post-logout URL; provider (Keycloak) configured without post_logout_redirect_uri so state handling differs; interrupted logout flow.

Related errors


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