quarkusio/quarkus · error · IllegalStateException

OIDC Client Registration is closed

Error message

OIDC Client Registration is closed

What it means

OidcClientRegistrationImpl.checkClosed throws IllegalStateException once close() has been called on the registration client. After closing, all operations (registerClient, registerClients, registeredClient, readClient) are rejected because the underlying resources were released. This is a lifecycle misuse error, not a server-side problem.

Source

Thrown at extensions/oidc-client-registration/runtime/src/main/java/io/quarkus/oidc/client/registration/runtime/OidcClientRegistrationImpl.java:234

                requestFilters, responseFilters, createMetadata(oidcConfig.metadata()), registrationUri, registrationToken);
        return newClient.read();
    }

    @Override
    public void close() throws IOException {
        if (!closed) {
            try {
                client.close();
            } catch (Exception ex) {
                LOG.debug("Failed to close the client", ex);
            }
            closed = true;
        }
    }

    private void checkClosed() {
        if (closed) {
            throw new IllegalStateException("OIDC Client Registration is closed");
        }
    }

    static class ClientRegistrationHelper {
        RegisteredClient client;
        String registrationUri;

        ClientRegistrationHelper(RegisteredClient client, String registrationUri) {
            this.client = client;
            this.registrationUri = registrationUri;
        }
    }

    static ClientMetadata createMetadata(Metadata metadata) {
        JsonObjectBuilder json = jsonProvider().createObjectBuilder();
        if (metadata.clientName().isPresent()) {
            json.add(OidcConstants.CLIENT_METADATA_CLIENT_NAME, metadata.clientName().get());
        }

View on GitHub (pinned to e1c734241f)

Solutions

  1. Do not call close() until all registration operations are complete
  2. Obtain a fresh OidcClientRegistration instance from the recorder/CDI instead of reusing a closed one
  3. Guard long-running registration tasks with a check that the client is still open

Example fix

// before
client.close();
client.registerClient(metadata); // IllegalStateException
// after
client.registerClient(metadata);
client.close(); // close only after all operations
Defensive patterns

Strategy: try-catch

Validate before calling

null

Type guard

null

Try / catch

try {
    client.registerClient(metadata).await().indefinitely();
} catch (IllegalStateException e) {
    if (e.getMessage().contains("is closed")) {
        client = oidcClientRegistrations.get(name); // re-acquire
    } else throw e;
}

Prevention

When it happens

Trigger: Calling registerClient(...) or registerClients(...) on an OidcClientRegistration instance after invoking close() on it — e.g. using a client obtained from a different lifecycle scope than the one that closed it.

Common situations: Application shutdown hooks closing the registration client while background tasks still register clients; calling close() in a finally block then retrying; reusing a request-scoped closed client.

Related errors


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