{"record":{"id":"c0a4aa8983218d2d","repo":"quarkusio/quarkus","slug":"tenant-configuration-has-not-been-resolved","errorCode":null,"errorMessage":"Tenant configuration has not been resolved","messagePattern":"Tenant configuration has not been resolved","errorType":"exception","errorClass":"OIDCException","httpStatus":401,"severity":"error","filePath":"extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/OidcAuthenticationMechanism.java","lineNumber":91,"sourceCode":"                return isWebApp(context, oidcTenantConfig) ? codeAuth.getChallenge(context)\n                        : bearerAuth.getChallenge(context);\n            }\n        });\n    }\n\n    private Uni<OidcTenantConfig> resolve(RoutingContext context) {\n        OidcTenantConfig resolvedConfig = context.get(OidcTenantConfig.class.getName());\n        if (resolvedConfig != null) {\n            return Uni.createFrom().item(resolvedConfig);\n        }\n\n        setTenantIdAttribute(context);\n\n        return resolver.resolveConfig(context).map(new Function<>() {\n            @Override\n            public OidcTenantConfig apply(OidcTenantConfig oidcTenantConfig) {\n                if (oidcTenantConfig == null) {\n                    throw new OIDCException(\"Tenant configuration has not been resolved\");\n                }\n                final String tenantId = oidcTenantConfig.tenantId().orElse(OidcUtils.DEFAULT_TENANT_ID);\n                LOG.debugf(\"Resolved OIDC tenant id: %s\", tenantId);\n                context.put(OidcTenantConfig.class.getName(), oidcTenantConfig);\n                if (context.get(OidcUtils.TENANT_ID_ATTRIBUTE) == null) {\n                    context.put(OidcUtils.TENANT_ID_ATTRIBUTE, tenantId);\n                }\n                return oidcTenantConfig;\n            };\n        });\n    }\n\n    private boolean isWebApp(RoutingContext context, OidcTenantConfig oidcConfig) {\n        ApplicationType applicationType = oidcConfig.applicationType().orElse(ApplicationType.SERVICE);\n        if (ApplicationType.HYBRID == applicationType) {\n            return context.request().getHeader(\"Authorization\") == null;\n        }\n        return ApplicationType.WEB_APP == applicationType;","sourceCodeStart":73,"sourceCodeEnd":109,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/OidcAuthenticationMechanism.java#L73-L109","documentation":"OidcAuthenticationMechanism.apply() resolves the tenant configuration for the incoming request. If resolver.resolveConfig() completes with a null OidcTenantConfig, OIDCException 'Tenant configuration has not been resolved' is thrown because authentication cannot proceed without a tenant.","triggerScenarios":"A custom TenantConfigResolver returns Uni.createFrom().item(null) (or null item) for a request; dynamic tenant resolution fails to match the request (path/host/header) and the resolver still emits null instead of failing or falling back to the default tenant.","commonSituations":"Multi-tenant apps where the resolver's matching logic doesn't cover all hosts/paths; requests hitting an unmapped tenant at boot before dynamic tenants are registered; typos in tenant identifiers within the resolver.","solutions":["In your TenantConfigResolver, return a valid OidcTenantConfig or fall back to the default tenant instead of emitting null.","If the tenant genuinely cannot be authenticated for this request, return Uni.createFrom().failure(new AuthenticationFailedException(...)) so OIDC treats it as an auth failure rather than an internal error.","Check resolver matching logic (host header, path prefix, query parameter) against the actual incoming request and add a catch-all mapping."],"exampleFix":"// before\npublic Uni<OidcTenantConfig> resolve(RoutingContext ctx) {\n    return tenants.containsKey(name(ctx)) ? Uni.createFrom().item(tenants.get(name(ctx))) : Uni.createFrom().item((OidcTenantConfig) null);\n}\n\n// after\npublic Uni<OidcTenantConfig> resolve(RoutingContext ctx) {\n    OidcTenantConfig cfg = tenants.get(name(ctx));\n    return cfg != null ? Uni.createFrom().item(cfg)\n        : Uni.createFrom().failure(new AuthenticationFailedException(\"Unknown tenant\"));\n}","handlingStrategy":"validation","validationCode":"public Uni<OidcTenantConfig> resolve(RoutingContext ctx) {\n    OidcTenantConfig cfg = lookup(ctx);\n    if (cfg == null) {\n        return Uni.createFrom().failure(new AuthenticationFailedException(\"Unknown tenant\"));\n    }\n    return Uni.createFrom().item(cfg);\n}","typeGuard":"boolean isResolved(OidcTenantConfig cfg) {\n    return cfg != null && cfg.tenantId().isPresent();\n}","tryCatchPattern":"try {\n    await().atMost(5, SECONDS).until(() -> resolver.resolve(ctx).await().indefinitely() != null);\n} catch (Exception e) {\n    // fall back to default tenant or reject request\n}","preventionTips":["Never emit null from TenantConfigResolver; fail with AuthenticationFailedException instead","Add a catch-all tenant mapping in the resolver","Test resolver matching with all expected hosts/paths","Log unmatched tenant lookups to spot gaps early"],"tags":["oidc","multi-tenancy","tenant-resolution"],"backgroundTag":"tenant-not-resolved","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"}