{"record":{"id":"187c59aa95fada57","repo":"quarkusio/quarkus","slug":"oidcproviderclient-can-not-be-injected","errorCode":null,"errorMessage":"OidcProviderClient can not be injected","messagePattern":"OidcProviderClient can not be injected","errorType":"exception","errorClass":"OIDCException","httpStatus":500,"severity":"error","filePath":"extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/OidcConfigurationAndProviderProducer.java","lineNumber":51,"sourceCode":"    @Produces\n    @RequestScoped\n    OidcProviderClient produceProviderClient() {\n        OidcProviderClient client = null;\n        String tenantId = OidcUtils.getAttribute(identity, OidcUtils.TENANT_ID_ATTRIBUTE);\n        if (tenantId != null) {\n            if (OidcUtils.DEFAULT_TENANT_ID.equals(tenantId)) {\n                return tenantConfig.getDefaultTenant().getOidcProviderClient();\n            }\n            TenantConfigContext context = tenantConfig.getStaticTenant(tenantId);\n            if (context == null) {\n                context = tenantConfig.getDynamicTenant(tenantId);\n            }\n            if (context != null) {\n                client = context.getOidcProviderClient();\n            }\n        }\n        if (client == null) {\n            throw new OIDCException(\"OidcProviderClient can not be injected\");\n        }\n        return client;\n    }\n}\n","sourceCodeStart":33,"sourceCodeEnd":56,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/OidcConfigurationAndProviderProducer.java#L33-L56","documentation":"produceProviderClient() resolves the OidcProviderClient from the SecurityIdentity's TENANT_ID_ATTRIBUTE (default tenant, static tenant, or dynamic tenant). If the attribute is missing or maps to no known tenant, the client is null and OIDCException 'OidcProviderClient can not be injected' is thrown.","triggerScenarios":"Inject OidcProviderClient in a request where SecurityIdentity lacks a TENANT_ID_ATTRIBUTE (unauthenticated or non-OIDC identity), or the attribute references a tenant not registered in tenantConfig (tenant removed/renamed while a session references the old id).","commonSituations":"Injecting OidcProviderClient into endpoints that allow anonymous access or use another IdentityProvider; stale sessions for a tenant deleted from configuration; using dynamic tenants resolved lazily so no client is bound yet at injection time.","solutions":["Only inject OidcProviderClient in endpoints secured by OIDC (enforce authentication, e.g. quarkus.http.auth.permission policies) so TENANT_ID_ATTRIBUTE is set.","Look up the client explicitly via TenantConfigBean (getDefaultTenant()/getStaticTenant(tenantId)) instead of injecting the produced bean.","Ensure tenant names in configuration match those recorded in existing sessions after refactors; restart users through login if tenant ids changed."],"exampleFix":"// before\n@Inject OidcProviderClient client; // null on anonymous endpoints\n\n// after\n@Inject TenantConfigBean tenantConfig;\nOidcProviderClient client = tenantConfig.getStaticTenant(\"hr\").getOidcProviderClient();","handlingStrategy":"type-guard","validationCode":"String tenantId = OidcUtils.getAttribute(identity, OidcUtils.TENANT_ID_ATTRIBUTE);\nif (tenantId == null || tenantConfig.getStaticTenant(tenantId) == null) {\n    // endpoint not secured by OIDC or tenant no longer exists - avoid injecting\n}","typeGuard":"boolean hasProviderClient(SecurityIdentity identity, TenantConfigBean cfg) {\n    String tenantId = OidcUtils.getAttribute(identity, OidcUtils.TENANT_ID_ATTRIBUTE);\n    if (tenantId == null) return false;\n    if (OidcUtils.DEFAULT_TENANT_ID.equals(tenantId)) return true;\n    return cfg.getStaticTenant(tenantId) != null || cfg.getDynamicTenant(tenantId) != null;\n}","tryCatchPattern":"try {\n    return client.introspect(token).await().indefinitely();\n} catch (OIDCException e) {\n    if (e.getMessage().contains(\"OidcProviderClient\")) {\n        // request has no OIDC identity; respond 401 instead of 500\n    }\n    throw e;\n}","preventionTips":["Secure endpoints that inject OidcProviderClient with OIDC auth requirements","Look up clients via TenantConfigBean rather than injecting the producer","Keep tenant ids stable across config refactors, or invalidate stale sessions","Handle anonymous traffic in separate beans without OIDC injections"],"tags":["oidc","cdi","tenant","request-scoped"],"backgroundTag":"unavailable-cdi-dependency","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}