{"record":{"id":"af3786baa346b147","repo":"quarkusio/quarkus","slug":"resource-metadata-path-cannot-contain-a-wildcard","errorCode":null,"errorMessage":"Resource metadata path cannot contain a wildcard '*' character","messagePattern":"Resource metadata path cannot contain a wildcard '\\*' character","errorType":"validation","errorClass":"java.lang.IllegalStateException","httpStatus":null,"severity":"error","filePath":"extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/ResourceMetadataHandler.java","lineNumber":76,"sourceCode":"    }\n\n    synchronized void updatePathMatcher(@Observes NewResourceMetadata ignored) {\n        createOrUpdatePathMatcher();\n    }\n\n    private void createOrUpdatePathMatcher() {\n        ImmutablePathMatcher.ImmutablePathMatcherBuilder<Handler<RoutingContext>> builder = null;\n        Map<String, OidcTenantConfig> pathCache = null;\n        for (TenantConfigContext configContext : resolver.getTenantConfigBean().getAllTenantConfigs()) {\n            if (configContext.ready() && configContext.oidcConfig().tenantEnabled()\n                    && configContext.oidcConfig().resourceMetadata().enabled()) {\n                if (builder == null) {\n                    builder = ImmutablePathMatcher.builder();\n                    pathCache = new HashMap<>();\n                }\n                String routePath = getResourceMetadataPath(configContext.oidcConfig(), resolver.getRootPath());\n                if (routePath.contains(\"*\")) {\n                    throw new IllegalStateException(\"Resource metadata path cannot contain a wildcard '*' character\");\n                }\n                OidcTenantConfig previousConfig = pathCache.put(routePath, configContext.oidcConfig());\n                if (previousConfig == null) {\n                    Handler<RoutingContext> routeHandler = new RouteHandler(configContext.oidcConfig(), resolver);\n                    builder.addPath(routePath, routeHandler);\n                } else {\n                    String previousTenantId = previousConfig.tenantId().get();\n                    String currentTenantId = configContext.oidcConfig().tenantId().get();\n                    // maybe invalid state, but technically it could happen that some produces a static tenant with\n                    // a same id as a dynamic tenant\n                    if (!previousTenantId.equals(currentTenantId)) {\n                        String errorMessage = \"OIDC tenants '%s' and '%s' share the same resource metadata path '%s', which is not supported\"\n                                .formatted(previousTenantId, currentTenantId, routePath);\n                        LOG.error(errorMessage);\n                        throw new OIDCException(errorMessage);\n                    }\n                }\n            }","sourceCodeStart":58,"sourceCodeEnd":94,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/ResourceMetadataHandler.java#L58-L94","documentation":"The OIDC resource metadata (RFC 9728) path handler in ResourceMetadataHandler.createOrUpdatePathMatcher throws IllegalStateException when a tenant's resource metadata path contains a wildcard '*'. Wildcard routes are unsupported for serving the /.well-known resource metadata documents.","triggerScenarios":"Configuring quarkus.oidc.<tenant>.resource-metadata (or a TenantResolver-provided config) whose computed path (getResourceMetadataPath, based on the tenant's base path or root path) contains '*', then building the path matcher during setup or updatePathMatcher.","commonSituations":"Misconfigured tenant root/base path containing wildcard patterns; copying a route-pattern style path into OIDC resource metadata configuration; dynamic tenant configs built from user input containing '*'.","solutions":["Remove the '*' character from the tenant's resource metadata / base path configuration","Configure explicit, literal paths for resource metadata endpoints","Validate dynamically supplied tenant root paths before passing them to OidcTenantConfig"],"exampleFix":"// before\nquarkus.oidc.tenant-a.resource-metadata.base-path=/api/*\n// after\nquarkus.oidc.tenant-a.resource-metadata.base-path=/api/tenant-a","handlingStrategy":"validation","validationCode":"String path = config.resourceMetadataBasePath();\nif (path != null && path.contains(\"*\")) throw new IllegalArgumentException(\"resource metadata path cannot contain '*'\");","typeGuard":null,"tryCatchPattern":"try { startApplication(); } catch (IllegalStateException e) { fail(\"Fix tenant resource-metadata path: \" + e.getMessage()); }","preventionTips":["Use literal paths only in resource-metadata configuration","Validate tenant base paths loaded from external sources before building OidcTenantConfig","Add a config-validation unit test rejecting '*' in OIDC paths"],"tags":["oidc","configuration","resource-metadata","wildcard"],"backgroundTag":"invalid-config-path-wildcard","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"}