{"record":{"id":"4aac1d14702fb9ea","repo":"quarkusio/quarkus","slug":"multiple-interface-io-quarkus-oidc-userinfo-beans","errorCode":null,"errorMessage":"Multiple interface io.quarkus.oidc.UserInfo beans registered","messagePattern":"Multiple interface io\\.quarkus\\.oidc\\.UserInfo beans registered","errorType":"console","errorClass":"IllegalStateException","httpStatus":null,"severity":"critical","filePath":"extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/DefaultTenantConfigResolver.java","lineNumber":107,"sourceCode":"        this.annotationBasedTenantResolutionEnabled = Boolean.getBoolean(OidcUtils.ANNOTATION_BASED_TENANT_RESOLUTION_ENABLED);\n        this.rootPath = rootPath;\n        this.staticTenantResolver = new StaticTenantResolver(tenantConfigBean, rootPath, resolveTenantsWithIssuer,\n                tenantResolverInstance);\n    }\n\n    @PostConstruct\n    public void verifyResolvers() {\n        if (tenantConfigResolver.isResolvable() && tenantConfigResolver.isAmbiguous()) {\n            throw new IllegalStateException(\"Multiple \" + TenantConfigResolver.class + \" beans registered\");\n        }\n        if (tokenStateManager.isAmbiguous()) {\n            throw new IllegalStateException(\"Multiple \" + TokenStateManager.class + \" beans registered\");\n        }\n        if (tokenIntrospectionCache.isAmbiguous()) {\n            throw new IllegalStateException(\"Multiple \" + TokenIntrospectionCache.class + \" beans registered\");\n        }\n        if (userInfoCache.isAmbiguous()) {\n            throw new IllegalStateException(\"Multiple \" + UserInfo.class + \" beans registered\");\n        }\n        if (javaScriptRequestChecker.isAmbiguous()) {\n            throw new IllegalStateException(\"Multiple \" + JavaScriptRequestChecker.class + \" beans registered\");\n        }\n\n    }\n\n    List<AuthenticationCompletionAction> authenticationCompletionActions() {\n        return authenticationCompletionActions;\n    }\n\n    Uni<OidcTenantConfig> resolveConfig(RoutingContext context) {\n        return getDynamicTenantConfig(context)\n                .flatMap(new Function<OidcTenantConfig, Uni<? extends OidcTenantConfig>>() {\n                    @Override\n                    public Uni<OidcTenantConfig> apply(OidcTenantConfig oidcTenantConfig) {\n                        if (oidcTenantConfig != null) {\n                            return Uni.createFrom().item(oidcTenantConfig);","sourceCodeStart":89,"sourceCodeEnd":125,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/DefaultTenantConfigResolver.java#L89-L125","documentation":"verifyResolvers() reports ambiguity of the UserInfo cache: more than one bean implementing io.quarkus.oidc.UserInfo (used as a cache/provider abstraction for UserInfo endpoint results) is registered. Note the message text names UserInfo even though the checked field is userInfoCache; startup fails so OIDC can guarantee a single UserInfo source.","triggerScenarios":"Register multiple beans whose type is UserInfo (or implementing the UserInfo cache abstraction injected as userInfoCache) so userInfoCache.isAmbiguous() is true in DefaultTenantConfigResolver's @PostConstruct.","commonSituations":"Customizing UserInfo handling while a default producer also exists; accidental duplicate producer methods (@Produces UserInfo) in different beans; copy-pasted CDI producers from another project.","solutions":["Remove or un-annotate all but one UserInfo bean/producer.","Mark the desired bean @Alternative with @Priority so it is the only resolvable one.","Review @Produces methods returning UserInfo and consolidate them into a single producer."],"exampleFix":"// before\n@Produces @ApplicationScoped UserInfo userInfoA() { ... }\n@Produces @ApplicationScoped UserInfo userInfoB() { ... } // ambiguous\n\n// after - only one producer remains\n@Produces @ApplicationScoped UserInfo userInfoA() { ... }","handlingStrategy":"validation","validationCode":"if (CDI.current().select(UserInfo.class).stream().count() > 1) {\n    throw new IllegalStateException(\"Duplicate UserInfo producers detected\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Grep for '@Produces' methods returning UserInfo and consolidate them","Avoid copy-pasting CDI producers from other projects","Document the single UserInfo producer as the app's source of truth"],"tags":["cdi","oidc","startup","userinfo"],"backgroundTag":"ambiguous-cdi-bean","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"}