screenpipe/screenpipe · error

{}

Error message

{}

What it means

Terminal error of fetch_first_json: after trying every candidate metadata URL, none succeeded. The message is the last recorded failure — either '<url> returned <status>: <body>' for HTTP errors or '<url>: <reqwest error>' for transport failures, or 'no OAuth metadata URLs to try' when the list was empty.

Source

Thrown at crates/screenpipe-connect/src/mcp_servers.rs:863

                    continue;
                }
            };
            let status = response.status();
            let text = response
                .text()
                .await
                .map_err(|e| anyhow!("failed to read OAuth metadata from {}: {}", url, e))?;
            if status.is_success() {
                return Ok((url.clone(), text));
            }
            last_error = Some(format!(
                "{} returned {}: {}",
                url,
                status,
                truncate(&text, 400)
            ));
        }
        Err(anyhow!(
            "{}",
            last_error.unwrap_or_else(|| "no OAuth metadata URLs to try".to_string())
        ))
    }

    /// Returns `(client_id, client_secret)`. The secret is `Some` only when the
    /// server registers us as a confidential client (and then it must be
    /// presented on every token / refresh request).
    async fn register_oauth_client(
        &self,
        registration_endpoint: Option<&str>,
        redirect_uri: &str,
    ) -> Result<(String, Option<String>)> {
        let Some(registration_endpoint) = registration_endpoint else {
            return Err(anyhow!(
                "OAuth server does not advertise dynamic client registration"
            ));
        };

View on GitHub (pinned to 4ebf712990)

Solutions

  1. Read the embedded last_error in the message: it names the URL, status, and body snippet that failed last.
  2. curl the metadata URL shown in the message to reproduce outside the app.
  3. Verify the MCP server's /.well-known/oauth-protected-resource advertises a valid authorization_servers entry.
  4. Check that the auth server is reachable (DNS/VPN/firewall) and not returning 5xx.
Defensive patterns

Strategy: fallback

Validate before calling

// verify discovery candidates resolve and respond before invoking the flow
for url in metadata_urls {
    let ok = reqwest::get(url).await.map(|r| r.status().is_success()).unwrap_or(false);
    assert!(ok, "metadata URL unreachable: {}", url);
}

Try / catch

match result {
    Err(e) if e.to_string() == "no OAuth metadata URLs to try" => {
        // configure authorization endpoints manually via oauth.token_url / oauth.auth_url
        configure_manual_oauth_endpoints().await
    }
    Err(e) => return Err(e),
    Ok(v) => Ok(v),
}

Prevention

When it happens

Trigger: OAuth discovery against an MCP server where all authorization-server metadata URLs return non-2xx (404, 502, 401...) or all fail at the transport layer; also when authorization_server_metadata_urls produced no candidates.

Common situations: Auth server is down or behind a 5xx-ing proxy, the MCP server advertises an authorization_servers URL that 404s, network/VPN blocks the auth domain, or metadata URL construction yields an empty list.

Related errors


AI-assisted analysis of screenpipe/screenpipe@4ebf712990 (2026-09-01). Data as JSON: /api/errors/d1db3d4744c6c5f9. Report an issue: GitHub.