{"record":{"id":"49ec2b290b1a9784","repo":"apache/pulsar","slug":"metadata-path-must-start-with-well-known-prefix","errorCode":null,"errorMessage":"Metadata path must start with '${WELL_KNOWN_PREFIX}', but was: ${wellKnownMetadataPath}","messagePattern":"Metadata path must start with '(.+?)', but was: (.+?)","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"pulsar-client/src/main/java/org/apache/pulsar/client/impl/auth/oauth2/protocol/DefaultMetadataResolver.java","lineNumber":90,"sourceCode":"     * @return a URL\n     * @see <a href=\"https://tools.ietf.org/id/draft-ietf-oauth-discovery-08.html#ASConfig\">\n     * OAuth Discovery: Obtaining Authorization Server Metadata</a>\n     */\n    public static URL getWellKnownMetadataUrl(URL issuerUrl, String wellKnownMetadataPath) {\n        try {\n            if (wellKnownMetadataPath == null || wellKnownMetadataPath.isEmpty()) {\n                return URI.create(issuerUrl.toExternalForm() + DEFAULT_WELL_KNOWN_METADATA_PATH).normalize().toURL();\n            }\n            if (wellKnownMetadataPath.startsWith(WELL_KNOWN_PREFIX)) {\n                String issuerUrlString = issuerUrl.toExternalForm();\n                // For OAuth2, insert well-known path before the issuer URL path\n                URL url = new URL(issuerUrlString);\n                String path = url.getPath();\n                String basePath = issuerUrlString.substring(0,\n                        issuerUrlString.length() - (path.isEmpty() ? 0 : path.length()));\n                return URI.create(basePath + wellKnownMetadataPath + path).normalize().toURL();\n            } else {\n                throw new IllegalArgumentException(\"Metadata path must start with '\" + WELL_KNOWN_PREFIX\n                        + \"', but was: \" + wellKnownMetadataPath);\n            }\n        } catch (MalformedURLException e) {\n            throw new IllegalArgumentException(e);\n        }\n    }\n\n    /**\n     * Resolves the authorization metadata.\n     *\n     * @return metadata\n     * @throws IOException if the metadata could not be resolved.\n     */\n    public Metadata resolve() throws IOException {\n\n        try {\n            HttpRequest request = HttpRequest.builder(HttpRequest.Method.GET, URI.create(metadataUrl.toString()))\n                    .header(\"Accept\", \"application/json\")","sourceCodeStart":72,"sourceCodeEnd":108,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-client/src/main/java/org/apache/pulsar/client/impl/auth/oauth2/protocol/DefaultMetadataResolver.java#L72-L108","documentation":"DefaultMetadataResolver.getWellKnownMetadataUrl builds the OIDC discovery URL by appending a well-known metadata path (e.g. /.well-known/openid-configuration) under the issuer URL. If the configured wellKnownMetadataPath does not start with the required WELL_KNOWN_PREFIX ('/.well-known/'), this IllegalArgumentException is thrown. Only spec-conformant discovery paths are supported.","triggerScenarios":"Constructing a DefaultMetadataResolver (via fromIssuerUrl) with a custom wellKnownMetadataPath value that lacks the '/.well-known/' prefix — e.g. 'openid-configuration', '/oauth2/.well-known/...', or a typo like '/.well-known/openid-configuration2' without the leading segment.","commonSituations":"Customizing the discovery path for a non-standard IdP and forgetting the prefix; typos when overriding defaults; confusing a full token/discovery URL with just the path component.","solutions":["Prefix the path with '/.well-known/' (e.g. '/.well-known/openid-configuration' or '/.well-known/oauth-authorization-server').","If the IdP is non-standard, keep the standard discovery path or serve metadata at a spec-conformant location.","Check the path actually begins with the prefix character-for-character, including the leading slash."],"exampleFix":"// before\nnew DefaultMetadataResolver(executor).fromIssuerUrl(\"https://idp.example.com\", \"openid-configuration\"); // throws\n// after\nnew DefaultMetadataResolver(executor).fromIssuerUrl(\"https://idp.example.com\", \"/.well-known/openid-configuration\");","handlingStrategy":"validation","validationCode":"static void validateWellKnownPath(String p) {\n    if (p == null || !p.startsWith(\"/.well-known/\")) {\n        throw new IllegalArgumentException(\"wellKnownMetadataPath must start with '/.well-known/': \" + p);\n    }\n}","typeGuard":"boolean isWellKnownPath(String p) {\n    return p != null && p.startsWith(\"/.well-known/\");\n}","tryCatchPattern":"try {\n    resolver.fromIssuerUrl(issuerUrl, customMetadataPath);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().startsWith(\"Metadata path must start with\")) {\n        throw new ConfigException(\"Use a '/.well-known/...' discovery path: \" + e.getMessage(), e);\n    }\n    throw e;\n}","preventionTips":["Always build custom metadata paths under '/.well-known/', e.g. '/.well-known/oauth-authorization-server'.","Don't confuse a full discovery URL with the path component expected here.","Test resolver construction in CI with the exact path configured for your IdP."],"tags":["oauth2","openid-connect","discovery","configuration","pulsar-client"],"backgroundTag":"invalid-discovery-path","analyzedSha":"820761864ed8e2a7d2e52dd9763ad2ae117c1395","analyzedAt":"2026-09-06T00:14:20.138Z","contentChangedAt":"2026-09-06T00:14:20.138Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}