quarkusio/quarkus · error · io.quarkus.runtime.configuration.ConfigurationException

Token decryption key for tenant %s can not be read from %s

Error message

Token decryption key for tenant %s can not be read from %s

What it means

TenantConfigContextImpl.createTokenDecryptionKey throws ConfigurationException when the token decryption key file configured via quarkus.oidc.<tenant>.token.decryption-key-location cannot be read. Reading is delegated to OidcUtils.readDecryptionKey and any failure (missing file, malformed PEM) is wrapped with the tenant id and location.

Source

Thrown at extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/TenantConfigContextImpl.java:110

    @Override
    public Map<Redirect.Location, List<OidcRedirectFilter>> getLocationToRedirectFilters() {
        return redirectFilters;
    }

    private static boolean providerIsNoNull(OidcProvider provider) {
        return provider != null && provider.client != null;
    }

    private static Key createTokenDecryptionKey(OidcProvider provider, String clientSecret) {
        Key key = null;

        OidcTenantConfig oidcConfig = provider.oidcConfig;
        if (oidcConfig.token().decryptionKeyLocation().isPresent()) {
            try {
                return OidcUtils.readDecryptionKey(oidcConfig.token().decryptionKeyLocation().get());
            } catch (Exception ex) {
                throw new ConfigurationException(
                        String.format("Token decryption key for tenant %s can not be read from %s",
                                oidcConfig.tenantId().get(), oidcConfig.token().decryptionKeyLocation().get()),
                        ex);
            }
        }

        if (oidcConfig.token().decryptIdToken().orElse(false) || oidcConfig.token().decryptAccessToken()) {
            if (provider.client.getClientJwtKey() != null) {
                key = provider.client.getClientJwtKey();
            } else if (clientSecret != null) {
                key = OidcUtils.createSecretKeyFromDigest(clientSecret);
            }
        }
        return key;
    }

    private static SecretKey createStateSecretKey(OidcTenantConfig config, String possiblePkceSecret) {
        if (config.authentication().pkceRequired().orElse(false) || config.authentication().nonceRequired()) {

View on GitHub (pinned to e1c734241f)

Solutions

  1. Fix quarkus.oidc.<tenant>.token.decryption-key-location to point to an existing readable PEM private key file
  2. Verify the file is mounted/available in the runtime environment (container volume, k8s secret path)
  3. Re-export the key in valid PEM (PKCS#8) format if the format is wrong

Example fix

// before
quarkus.oidc.tenant-b.token.decryption-key-location=/wrong/path/key.pem
// after
quarkus.oidc.tenant-b.token.decryption-key-location=/deployments/keys/tenant-b-key.pem
Defensive patterns

Strategy: validation

Validate before calling

Path keyPath = Path.of(config.decryptionKeyLocation());
if (!Files.isReadable(keyPath)) throw new IllegalStateException("Decryption key unreadable: " + keyPath);

Try / catch

try { startApplication(); } catch (ConfigurationException e) { log.error("Fix token.decryption-key-location: " + e.getMessage(), e.getCause()); }

Prevention

When it happens

Trigger: Building the tenant's ready context (createReady/tokenDecryptionKey) with oidcConfig.token().decryptionKeyLocation() present; OidcUtils.readDecryptionKey throws (file not found, unreadable, invalid PEM) and the exception is wrapped in ConfigurationException.

Common situations: Wrong path to the private key PEM; key mounted in a container at a different path; file permissions blocking read; key in DER/PKCS12 format not accepted as PEM.

Related errors


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