zed-industries/zed · error
Failed to connect to Mistral API: {} {}
Error message
Failed to connect to Mistral API: {} {} What it means
Raised by Zed's Mistral provider when POSTing to {api_url}/chat/completions returns a non-success HTTP status. The response body is drained and embedded verbatim next to the status code, so authentication, quota, model, and upstream-server failures all surface through this single message.
Source
Thrown at crates/mistral/src/mistral.rs:458
Ok(line) => {
let line = line.strip_prefix("data: ")?;
if line == "[DONE]" {
None
} else {
match serde_json::from_str(line) {
Ok(response) => Some(Ok(response)),
Err(error) => Some(Err(anyhow!(error))),
}
}
}
Err(error) => Some(Err(anyhow!(error))),
}
})
.boxed())
} else {
let mut body = String::new();
response.body_mut().read_to_string(&mut body).await?;
anyhow::bail!(
"Failed to connect to Mistral API: {} {}",
response.status(),
body,
);
}
}
View on GitHub (pinned to f4178619ac)
Solutions
- Read the status code and body inside the message: 401/403 → fix the API key in Zed's assistant settings; 404/400 → verify the model identifier; 429 → wait or raise rate limits; 5xx → retry shortly
- Confirm the key works outside Zed: curl https://api.mistral.ai/v1/chat/completions with the same key and model
- Check corporate proxy/VPN interference if the body is an HTML error page
- Retry after a short backoff — transient 429/5xx responses commonly clear on their own
Defensive patterns
Strategy: try-catch
Validate before calling
async fn key_works(client: &dyn HttpClient, api_key: &str) -> bool {
// cheap auth probe before wiring the provider
let req = HttpRequest::get("https://api.mistral.ai/v1/models")
.header("Authorization", format!("Bearer {}", api_key.trim()));
matches!(client.send(req).await, Ok(resp) if resp.status().is_success())
} Try / catch
match stream_chat_completion(request).await {
Err(err) => {
let msg = err.to_string();
if msg.contains("429") || msg.contains("50") && msg.contains("Mistral API") {
backoff.then_retry().await; // transient: rate limit / upstream
} else if msg.contains("401") {
prompt_for_new_api_key();
} else {
show_error(msg); // body text carries the provider detail
}
}
Ok(stream) => stream,
} Prevention
- Validate the API key with a cheap /v1/models call at configuration time
- Confirm model identifiers against current Mistral docs before hardcoding
- Wrap streaming calls in retry-with-backoff for 429/5xx only, never for 401/404
- Watch the embedded response body — it distinguishes auth vs quota vs model errors
When it happens
Trigger: Any Mistral chat/stream completion call where the API answers 401 (bad/expired API key), 403, 404 (wrong model name in the request payload), 422, 429 (rate limit/quota), or 5xx. Note the request already carries `Authorization: Bearer <api_key>`; a missing key fails earlier.
Common situations: Expired or mistyped MISTRAL_API_KEY; quota exhausted on the Mistral plan; requesting a model the key has no access to; corporate proxies returning HTML error pages with a 502/503.
Related errors
- Failed to connect to DeepSeek API: {} {}
- Failed to connect to API: {} {}
- Failed to connect to API: {} {}
- Failed to fetch experiments: {:?} Body: {}
- custom server error: {} - {}
AI-assisted analysis of zed-industries/zed@f4178619ac (2026-08-20).
Data as JSON: /api/errors/76e260ea6d9cfea7.
Report an issue: GitHub.