zed-industries/zed · error
Could not fetch Authorization Server Metadata for {}
Error message
Could not fetch Authorization Server Metadata for {} What it means
Discovery failed at the second stage: none of the Authorization Server Metadata candidate URLs (RFC 8414 /oauth-authorization-server well-known and OIDC Discovery /.well-known/openid-configuration, in MCP-spec priority order) could be fetched successfully. As with error 167, each individual failure is only logged at debug level and the final bail names just the issuer, so the root cause (DNS, TLS, 404, non-JSON, or an issuer-mismatch bail swallowed by the loop) requires debug logs to see. Note that a candidate can 'fail' via the issuer-mismatch bail in the Ok arm, which is caught by this same loop and retried on the next candidate before giving up.
Source
Thrown at crates/context_server/src/oauth.rs:847
.ok_or_else(|| anyhow!("missing authorization_endpoint"))?,
token_endpoint: response
.token_endpoint
.ok_or_else(|| anyhow!("missing token_endpoint"))?,
registration_endpoint: response.registration_endpoint,
scopes_supported: response.scopes_supported,
code_challenge_methods_supported: response.code_challenge_methods_supported,
client_id_metadata_document_supported: response
.client_id_metadata_document_supported
.unwrap_or(false),
});
}
Err(err) => {
log::debug!("Failed to fetch Auth Server Metadata from {}: {}", url, err);
}
}
}
bail!(
"Could not fetch Authorization Server Metadata for {}",
issuer
)
}
/// Run the full discovery flow: fetch resource metadata, then auth server
/// metadata, then select scopes. Client registration is resolved separately,
/// once the real redirect URI is known.
pub async fn discover(
http_client: &Arc<dyn HttpClient>,
server_url: &Url,
www_authenticate: &WwwAuthenticate,
) -> Result<OAuthDiscovery> {
let resource_metadata =
fetch_protected_resource_metadata(http_client, server_url, www_authenticate).await?;
let auth_server_url = resource_metadata
.authorization_serversView on GitHub (pinned to f4178619ac)
Solutions
- Verify the auth server serves metadata at either /.well-known/oauth-authorization-server or /.well-known/openid-configuration for the exact issuer path (curl both)
- Correct the authorization_servers entry in the Protected Resource Metadata so it names the real authorization server issuer
- Ensure the endpoint returns JSON with 200 and no auth wall; allowlist it in the proxy/SSO layer
- Turn on debug logging to see each candidate URL and its specific error before changing configuration
Example fix
# before: issuer points at the resource, auth metadata 404s "authorization_servers": ["https://mcp.example.com"] # after: issuer points at the actual authorization server "authorization_servers": ["https://auth.example.com"] # where https://auth.example.com/.well-known/openid-configuration returns 200 JSON
Defensive patterns
Strategy: try-catch
Validate before calling
// preflight both discovery endpoint styles for the issuer
async fn as_metadata_reachable(http: &Arc<dyn HttpClient>, issuer: &Url) -> bool {
auth_server_metadata_urls(issuer).iter().any(|u| {
fetch_json::<serde_json::Value>(http, u).await.is_ok()
})
} Try / catch
match fetch_auth_server_metadata(&client, &issuer).await {
Ok(meta) => Ok(meta),
Err(err) if err.to_string().contains("Could not fetch Authorization Server Metadata") => {
// candidates: /oauth-authorization-server and /openid-configuration; curl them to see which failed and why
if is_transient_network(&err) { retry_with_backoff().await } else { Err(err) }
}
Err(err) => Err(err),
} Prevention
- Confirm the auth server exposes RFC 8414 or OIDC discovery for the exact issuer path before advertising it in authorization_servers
- Make sure the well-known endpoints are unauthenticated and return application/json, not an SSO HTML page
- Keep debug logging on during setup: each candidate failure is logged individually before the aggregate bail
When it happens
Trigger: fetch_auth_server_metadata() iterates auth_server_metadata_urls(issuer); every fetch_json call returns Err — connection refused, 404 for both endpoint styles, HTML instead of JSON, or the Ok branch bailing on issuer mismatch for each candidate.
Common situations: Authorization server that is a plain OAuth2 server without OIDC discovery and without RFC 8414 endpoints; auth server behind auth-offloading proxy that returns an HTML login page on the well-known path; wrong issuer listed in authorization_servers (points at resource not auth server); network egress blocked to the auth domain.
Related errors
- Could not fetch Protected Resource Metadata for {}
- Protected Resource Metadata at {} has no authorization_serve
- Auth server metadata issuer mismatch: expected {}, got {}
- OAuth endpoint must use HTTPS (got {}://{})
- OAuth endpoint must not point to private/reserved IP: {}
AI-assisted analysis of zed-industries/zed@f4178619ac (2026-08-20).
Data as JSON: /api/errors/0842668fa6a36084.
Report an issue: GitHub.