quarkusio/quarkus · error · OIDCException
OidcConfigurationMetadata can not be injected
Error message
OidcConfigurationMetadata can not be injected
What it means
OidcConfigurationAndProviderProducer.produceMetadata() @Produces OidcConfigurationMetadata from the SecurityIdentity's CONFIG_METADATA_ATTRIBUTE, falling back to the default tenant's provider metadata. If neither is available, injection fails with OIDCException - the metadata is only present after successful authentication by the default (or identity-carrying) tenant.
Source
Thrown at extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/OidcConfigurationAndProviderProducer.java:28
import io.quarkus.security.identity.SecurityIdentity;
@RequestScoped
public class OidcConfigurationAndProviderProducer {
@Inject
TenantConfigBean tenantConfig;
@Inject
SecurityIdentity identity;
@Produces
@RequestScoped
OidcConfigurationMetadata produceMetadata() {
OidcConfigurationMetadata configMetadata = OidcUtils.getAttribute(identity, OidcUtils.CONFIG_METADATA_ATTRIBUTE);
if (configMetadata == null && tenantConfig.getDefaultTenant().oidcConfig().tenantEnabled()) {
configMetadata = tenantConfig.getDefaultTenant().provider().getMetadata();
}
if (configMetadata == null) {
throw new OIDCException("OidcConfigurationMetadata can not be injected");
}
return configMetadata;
}
@Produces
@RequestScoped
OidcProviderClient produceProviderClient() {
OidcProviderClient client = null;
String tenantId = OidcUtils.getAttribute(identity, OidcUtils.TENANT_ID_ATTRIBUTE);
if (tenantId != null) {
if (OidcUtils.DEFAULT_TENANT_ID.equals(tenantId)) {
return tenantConfig.getDefaultTenant().getOidcProviderClient();
}
TenantConfigContext context = tenantConfig.getStaticTenant(tenantId);
if (context == null) {
context = tenantConfig.getDynamicTenant(tenantId);
}
if (context != null) {View on GitHub (pinned to e1c734241f)
Solutions
- Enable the default tenant (quarkus.oidc.tenant-enabled=true) if your app actually authenticates against the default provider.
- Don't inject OidcConfigurationMetadata directly; instead obtain metadata from the TenantConfigContext/provider for the tenant you care about, or read it from the SecurityIdentity attribute yourself with a null check.
- Ensure injection happens only within an authenticated request (RequestScoped) and not during startup or scheduled tasks.
Example fix
// before
@Inject OidcConfigurationMetadata metadata; // fails when default tenant disabled
// after - fetch from the specific tenant's provider
@Inject TenantConfigBean tenantConfig;
OidcConfigurationMetadata metadata =
tenantConfig.getStaticTenant("my-tenant").getOidcProviderClient().getMetadata(); Defensive patterns
Strategy: try-catch
Validate before calling
boolean canInjectMetadata = OidcUtils.getAttribute(identity, OidcUtils.CONFIG_METADATA_ATTRIBUTE) != null
|| tenantConfig.getDefaultTenant().oidcConfig().tenantEnabled(); Type guard
boolean hasMetadata(SecurityIdentity identity, TenantConfigBean cfg) {
return OidcUtils.getAttribute(identity, OidcUtils.CONFIG_METADATA_ATTRIBUTE) != null
|| cfg.getDefaultTenant().oidcConfig().tenantEnabled();
} Try / catch
try {
return metadataService.call();
} catch (OIDCException e) {
if (e.getMessage().contains("OidcConfigurationMetadata")) {
// resolve metadata from the specific tenant provider instead
}
throw e;
} Prevention
- Don't keep quarkus.oidc.tenant-enabled=false if you inject default-tenant metadata
- Inject only inside authenticated request scope
- Fetch metadata from the tenant-specific provider when using named/dynamic tenants
- Add null-safe attribute reads instead of direct @Inject where tenants vary
When it happens
Trigger: Inject OidcConfigurationMetadata in a bean during a request where the SecurityIdentity has no CONFIG_METADATA_ATTRIBUTE and either the default tenant is disabled (quarkus.oidc.tenant-enabled=false) or the identity was produced by a non-default/dynamic tenant without that attribute.
Common situations: Injecting OidcConfigurationMetadata in apps using only named tenants or TenantConfigResolver-based dynamic tenants with the default tenant disabled; using the injection outside authenticated request scope (e.g. startup, background thread).
Related errors
- OidcProviderClient can not be injected
- %s type can not be used to represent JWT claims in @Singleto
- Multiple interface io.quarkus.oidc.TenantConfigResolver bean
- Multiple interface io.quarkus.oidc.runtime.TokenStateManager
- Multiple interface io.quarkus.oidc.runtime.TokenIntrospectio
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/fe2d864fc3a2ce0e.
Report an issue: GitHub.