Kuberwastaken/claurst · error · anyhow::Error
Bridge upload: server returned
Error message
Bridge upload: server returned {} What it means
Within `refresh_mcp_token`, after loading the stored token, the code reads `existing.refresh_token`. If the stored `McpToken` has no refresh token (the provider did not issue one during the original exchange), this error is returned. Without a refresh token the library cannot silently renew the credentials.
Solutions
- Re-run `run_mcp_auth_flow` to obtain a fresh token that includes a refresh token.
- Check the provider's requirements: request the scopes needed for refresh tokens (e.g. offline_access) in the authorization URL.
- Verify the token exchange actually returns a refresh_token field for this provider/client.
- Until re-auth, treat the token as non-renewable: re-authenticate each time it expires.
Example fix
// before: auth_url scopes may omit refresh-eligible scope
// after: include offline access so a refresh token is issued
let auth_url = format!(
"{}?response_type=code&client_id={}&redirect_uri={}&scope={} offline_access&state={}",
auth_endpoint, client_id, redirect_uri, scopes, state
); Defensive patterns
Strategy: fallback
Validate before calling
// before refreshing, check a refresh token is available
let can_refresh = get_mcp_token(server_name)
.and_then(|t| t.refresh_token)
.is_some(); Try / catch
match refresh_mcp_token(server, endpoint).await {
Ok(t) => t,
Err(e) if e.to_string().contains("has no refresh token") => {
run_mcp_auth_flow(&session).await? // re-auth required
}
Err(e) => return Err(e),
} Prevention
- Request offline_access (or the provider's refresh-eligible scope) in the authorization URL
- Re-authenticate after migrating tokens from versions that did not store refresh tokens
- Verify the provider issues refresh tokens for your client type
When it happens
Trigger: The stored token for `server_name` exists but `refresh_token` is None — the original authorization/token exchange did not yield a refresh token, and now `get_valid_mcp_token` attempts a refresh.
Common situations: Provider that only issues refresh tokens with specific scopes (e.g. Google requires offline access) or for certain client types; the original flow stored a short-lived token without a refresh grant; older stored tokens created before refresh support was added.
Related errors
- Bridge poll: server returned
- refresh: HTTP
- models endpoint returned
- Invalid JWT: expected at least 2 dot-separated segments
- Invalid : contains unsafe characters
AI-assisted analysis of Kuberwastaken/claurst@b0637c97ec (2026-09-10).
Data as JSON: /api/errors/fb3c755873e13072.
Report an issue: GitHub.
Appendix: source
Thrown at src-rust/crates/bridge/src/lib.rs:630
let resp = self
.http
.post(&url)
.bearer_auth(token)
.json(&body)
.send()
.await
.context("Bridge upload: HTTP send failed")?;
if !resp.status().is_success() {
let status = resp.status().as_u16();
warn!(
session_id = %self.session_id,
status,
count = events.len(),
"Bridge event upload failed"
);
anyhow::bail!("Bridge upload: server returned {}", status);
}
debug!(
session_id = %self.session_id,
count = events.len(),
"Bridge events uploaded"
);
Ok(())
}
// -----------------------------------------------------------------------
// Main poll loop
// -----------------------------------------------------------------------
/// Run the bridge poll loop until `cancel` is triggered or a fatal error
/// occurs.
///
/// On each iteration:
View on GitHub (pinned to b0637c97ec)