{"record":{"id":"1a691992c3dee7d7","repo":"tinyhumansai/openhuman","slug":"http-while-fetching","errorCode":null,"errorMessage":"HTTP {} while fetching {} — {}","messagePattern":"HTTP (.+?) while fetching (.+?) — (.+?)","errorType":"http","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"src/openhuman/mcp/http_client/client.rs","lineNumber":638,"sourceCode":"                    }\n                }\n                req\n            }\n            McpAuthConfig::QueryParam { name, value } => {\n                request.query(&[(name.as_str(), value.as_str())])\n            }\n        }\n    }\n\n    async fn fetch_json<T>(&self, url: &str) -> anyhow::Result<T>\n    where\n        T: for<'de> Deserialize<'de>,\n    {\n        let response = self.http.get(url).send().await?;\n        let status = response.status();\n        let text = response.text().await?;\n        if !status.is_success() {\n            anyhow::bail!(\"HTTP {} while fetching {} — {}\", status.as_u16(), url, text);\n        }\n        serde_json::from_str(&text).with_context(|| format!(\"parsing JSON from {url}\"))\n    }\n\n    async fn fetch_authorization_server_metadata(\n        &self,\n        issuer: &str,\n    ) -> anyhow::Result<AuthorizationServerMetadata> {\n        let trimmed = issuer.trim_end_matches('/');\n        let oidc = format!(\"{trimmed}/.well-known/openid-configuration\");\n        if let Ok(metadata) = self.fetch_json::<AuthorizationServerMetadata>(&oidc).await {\n            return Ok(metadata);\n        }\n        let oauth = format!(\"{trimmed}/.well-known/oauth-authorization-server\");\n        self.fetch_json::<AuthorizationServerMetadata>(&oauth).await\n    }\n\n    fn validate_protocol_version(&self, version: &str) -> anyhow::Result<()> {","sourceCodeStart":620,"sourceCodeEnd":656,"githubUrl":"https://github.com/tinyhumansai/openhuman/blob/749120085864ce16e0f273c7b86fac7740b39c5b/src/openhuman/mcp/http_client/client.rs#L620-L656","documentation":"`fetch_json` GETs a URL (used for OAuth discovery documents: `{issuer}/.well-known/openid-configuration` and `{issuer}/.well-known/oauth-authorization-server`) and got a non-2xx; the message embeds status, URL and body. In `fetch_authorization_server_metadata` the OIDC attempt is allowed to fail and falls back to the OAuth variant — this error only reaches you when the *last* attempt (the oauth-authorization-server document) also fails.","triggerScenarios":"OAuth discovery against an issuer that publishes neither well-known document, publishes them at a non-standard path, requires auth for metadata, or returns 404/401/5xx; a typo'd or redirected issuer URL.","commonSituations":"MCP servers whose auth server is a plain OAuth2 AS without OIDC discovery; issuer URL with trailing path confusion; corporate proxies intercepting well-known endpoints; dev servers without discovery enabled.","solutions":["Open both well-known URLs in a browser/curl and confirm one returns JSON metadata.","Fix the issuer/authorization URL — it must be the exact base the documents live under.","If the server publishes metadata at a custom path, configure that endpoint directly instead of relying on discovery.","If discovery genuinely is not supported, use static token auth for that server instead of OAuth."],"exampleFix":"# diagnose with:\n# curl -i https://issuer.example.com/.well-known/oauth-authorization-server\n# ensure it returns 200 + JSON before configuring OAuth for that MCP server","handlingStrategy":"try-catch","validationCode":"// before OAuth config, probe discovery yourself:\n// GET {issuer}/.well-known/openid-configuration\n// GET {issuer}/.well-known/oauth-authorization-server\n// at least one must return 200 JSON","typeGuard":null,"tryCatchPattern":"match client.discover_metadata(issuer).await {\n    Err(e) if e.to_string().contains(\"HTTP 404\") => {\n        // no discovery: fall back to static token auth for this server\n    }\n    other => other,\n}","preventionTips":["Verify both well-known URLs respond before enabling OAuth for a server.","Copy the issuer URL exactly — no trailing slash confusion, no path mixups.","For non-discovery auth servers, use static tokens instead of the OAuth flow."],"tags":["mcp","oauth","discovery","http"],"backgroundTag":"http-error-response","analyzedSha":"749120085864ce16e0f273c7b86fac7740b39c5b","analyzedAt":"2026-08-17T21:21:45.363Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}