{"record":{"id":"b6ebfd49a469e618","repo":"Kuberwastaken/claurst","slug":"oauth-metadata-parse-error","errorCode":null,"errorMessage":"OAuth metadata parse error: {}","messagePattern":"OAuth metadata parse error: (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"src-rust/crates/mcp/src/oauth.rs","lineNumber":172,"sourceCode":"        challenge,\n    )\n}\n\npub async fn fetch_oauth_metadata(server_url: &str) -> anyhow::Result<McpOAuthMetadata> {\n    let base_url = normalized_server_url(server_url);\n    let fallback = fallback_oauth_metadata(base_url);\n    let metadata_url = format!(\"{}/.well-known/oauth-authorization-server\", base_url);\n    let client = reqwest::Client::builder()\n        .timeout(Duration::from_secs(10))\n        .build()\n        .map_err(|e| anyhow::anyhow!(\"Failed to build HTTP client: {}\", e))?;\n\n    match client.get(&metadata_url).send().await {\n        Ok(resp) if resp.status().is_success() => {\n            let meta: serde_json::Value = resp\n                .json()\n                .await\n                .map_err(|e| anyhow::anyhow!(\"OAuth metadata parse error: {}\", e))?;\n            Ok(McpOAuthMetadata {\n                authorization_endpoint: meta\n                    .get(\"authorization_endpoint\")\n                    .and_then(|value| value.as_str())\n                    .unwrap_or(fallback.authorization_endpoint.as_str())\n                    .to_string(),\n                token_endpoint: meta\n                    .get(\"token_endpoint\")\n                    .and_then(|value| value.as_str())\n                    .unwrap_or(fallback.token_endpoint.as_str())\n                    .to_string(),\n            })\n        }\n        Ok(_) | Err(_) => Ok(fallback),\n    }\n}\n\npub async fn begin_mcp_auth(","sourceCodeStart":154,"sourceCodeEnd":190,"githubUrl":"https://github.com/Kuberwastaken/claurst/blob/b0637c97ec34144387cbf2f74f65df6d16a6cef1/src-rust/crates/mcp/src/oauth.rs#L154-L190","documentation":"When the well-known OAuth metadata endpoint responds successfully, the body is deserialized into serde_json::Value; a malformed or non-JSON body triggers this parse error. Fields like authorization_endpoint are then read with fallbacks, but the JSON itself must parse. Called by begin_mcp_auth and get_valid_mcp_token.","triggerScenarios":"fetch_oauth_metadata() gets a 2xx response from {base_url}/.well-known/oauth-authorization-server whose body is not valid JSON — HTML error pages, empty bodies with 200, or wrong content served by a proxy.","commonSituations":"Server behind an auth gateway returning an HTML login page with 200; base_url pointing at the wrong path so a generic page is returned; server returning XML or plain text; CDN error page with success status.","solutions":["Verify the base URL is the server root so the .well-known path resolves to real metadata","Check the response body manually with curl to see what is actually returned","Confirm the server implements RFC 8414 authorization-server metadata at that URL","Bypass intermediate proxies/gateways that rewrite the response body"],"exampleFix":"// before: hitting a path that returns HTML\nlet url = \"https://example.com/mcp\";\n// after: metadata is discovered from the server root\nlet url = \"https://mcp.example.com\"; // fetches {url}/.well-known/oauth-authorization-server","handlingStrategy":"fallback","validationCode":"let resp = reqwest::get(format!(\"{base}/.well-known/oauth-authorization-server\", base = server_url)).await?;\nlet ct = resp.headers().get(reqwest::header::CONTENT_TYPE)\n    .and_then(|v| v.to_str().ok()).unwrap_or(\"\");\nif !ct.contains(\"json\") {\n    anyhow::bail!(\"metadata endpoint returned non-JSON content-type: {ct}\");\n}","typeGuard":null,"tryCatchPattern":"let meta: serde_json::Value = resp.json().await\n    .map_err(|e| e.context(\"metadata endpoint did not return JSON; check base_url and proxies\"))?;","preventionTips":["Point the config url at the server root, not a page that returns HTML","Verify with curl that .well-known/oauth-authorization-server returns JSON","Bypass gateways that intercept 2xx with HTML challenge pages","Rely on the built-in fallback endpoints when discovery body is unreliable"],"tags":["oauth","json","http","parsing"],"backgroundTag":"json-parse-error","analyzedSha":"b0637c97ec34144387cbf2f74f65df6d16a6cef1","analyzedAt":"2026-09-10T00:24:58.650Z","contentChangedAt":"2026-09-10T00:24:58.650Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}