quarkusio/quarkus · error · OIDCException
Tenant configuration has not been resolved
Error message
Tenant configuration has not been resolved
What it means
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.
Source
Thrown at extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/OidcAuthenticationMechanism.java:91
return isWebApp(context, oidcTenantConfig) ? codeAuth.getChallenge(context)
: bearerAuth.getChallenge(context);
}
});
}
private Uni<OidcTenantConfig> resolve(RoutingContext context) {
OidcTenantConfig resolvedConfig = context.get(OidcTenantConfig.class.getName());
if (resolvedConfig != null) {
return Uni.createFrom().item(resolvedConfig);
}
setTenantIdAttribute(context);
return resolver.resolveConfig(context).map(new Function<>() {
@Override
public OidcTenantConfig apply(OidcTenantConfig oidcTenantConfig) {
if (oidcTenantConfig == null) {
throw new OIDCException("Tenant configuration has not been resolved");
}
final String tenantId = oidcTenantConfig.tenantId().orElse(OidcUtils.DEFAULT_TENANT_ID);
LOG.debugf("Resolved OIDC tenant id: %s", tenantId);
context.put(OidcTenantConfig.class.getName(), oidcTenantConfig);
if (context.get(OidcUtils.TENANT_ID_ATTRIBUTE) == null) {
context.put(OidcUtils.TENANT_ID_ATTRIBUTE, tenantId);
}
return oidcTenantConfig;
};
});
}
private boolean isWebApp(RoutingContext context, OidcTenantConfig oidcConfig) {
ApplicationType applicationType = oidcConfig.applicationType().orElse(ApplicationType.SERVICE);
if (ApplicationType.HYBRID == applicationType) {
return context.request().getHeader("Authorization") == null;
}
return ApplicationType.WEB_APP == applicationType;View on GitHub (pinned to e1c734241f)
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.
Example fix
// before
public Uni<OidcTenantConfig> resolve(RoutingContext ctx) {
return tenants.containsKey(name(ctx)) ? Uni.createFrom().item(tenants.get(name(ctx))) : Uni.createFrom().item((OidcTenantConfig) null);
}
// after
public Uni<OidcTenantConfig> resolve(RoutingContext ctx) {
OidcTenantConfig cfg = tenants.get(name(ctx));
return cfg != null ? Uni.createFrom().item(cfg)
: Uni.createFrom().failure(new AuthenticationFailedException("Unknown tenant"));
} Defensive patterns
Strategy: validation
Validate before calling
public Uni<OidcTenantConfig> resolve(RoutingContext ctx) {
OidcTenantConfig cfg = lookup(ctx);
if (cfg == null) {
return Uni.createFrom().failure(new AuthenticationFailedException("Unknown tenant"));
}
return Uni.createFrom().item(cfg);
} Type guard
boolean isResolved(OidcTenantConfig cfg) {
return cfg != null && cfg.tenantId().isPresent();
} Try / catch
try {
await().atMost(5, SECONDS).until(() -> resolver.resolve(ctx).await().indefinitely() != null);
} catch (Exception e) {
// fall back to default tenant or reject request
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- OIDC tenants '%s' and '%s' share the same back-channel logou
- Tenant id must have been set by either the session or state
- Failed to generate key id
- No instance of %1$s was found for persistence unit %2$s. You
- Method 'TenantResolver.getDefaultTenantId()' returned a null
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/c0a4aa8983218d2d.
Report an issue: GitHub.