xai-org/grok-build · error
Failed to parse upload response: {}
Error message
Failed to parse upload response: {} What it means
After a successful (2xx) upload HTTP request, the client parses the response body as JSON; if reqwest's response.json() fails, this error wraps the reqwest parse error. The upload itself reached the server successfully, but the returned body is not the JSON shape the client expects, so the result cannot be constructed.
Source
Thrown at crates/codegen/xai-file-utils/src/storage_client.rs:1209
),
}
.into());
}
let request = self.add_common_headers(
self.http_client
.post(&url)
.header("Content-Type", content_type)
.header("X-Storage-Path", path),
);
match request.body(content.clone()).send().await {
Ok(response) if response.status().is_success() => {
self.breaker.record(Outcome::Success);
return response
.json()
.await
.map_err(|e| anyhow::anyhow!("Failed to parse upload response: {}", e));
}
Ok(response) if response.status() == reqwest::StatusCode::UNAUTHORIZED => {
self.fire_401_attribution("upload");
self.breaker.record(Outcome::Failure);
return Err(HttpUploadError {
status_code: 401,
message: format!("{}: HTTP 401 Unauthorized", operation),
}
.into());
}
Ok(response) if response.status() == reqwest::StatusCode::FORBIDDEN => {
let body = response.text().await.unwrap_or_default();
tracing::warn!("storage upload rejected (403): {body}");
return Err(HttpUploadError {
status_code: 403,
message: format!("{operation}: HTTP 403 Forbidden - {body}"),
}
.into());View on GitHub (pinned to bc7f02eddd)
Solutions
- Log/inspect the raw response body and content-type to see what the server actually returned.
- Verify the storage endpoint/base URL points to the correct GCS proxy API version.
- Check for proxies/gateways rewriting responses and bypass or reconfigure them.
- Pin client and server versions so the upload response schema matches what the client parses.
Example fix
// before
return response.json().await
.map_err(|e| anyhow::anyhow!("Failed to parse upload response: {}", e));
// after
let body = response.text().await?;
serde_json::from_str(&body)
.map_err(|e| anyhow::anyhow!("Failed to parse upload response: {} (body: {:.200})", e, body)) Defensive patterns
Strategy: try-catch
Validate before calling
// Probe the endpoint returns JSON before uploading
let probe = reqwest::get(format!("{base}/health")).await?;
let ct = probe.headers().get(reqwest::header::CONTENT_TYPE);
if !ct.map(|v| v.to_str().unwrap_or_default().contains("json")).unwrap_or(false) {
anyhow::bail!("endpoint is not returning JSON; check base URL/proxy");
} Try / catch
// Catch parse failures and inspect the raw body
match client.upload(content).await {
Ok(resp) => use(resp),
Err(e) if e.to_string().starts_with("Failed to parse upload response") => {
eprintln!("server returned non-JSON: {e:#}; check proxy/base URL");
}
Err(e) => return Err(e),
} Prevention
- Point the client at the correct API base URL and version.
- Bypass proxies/CDNs that rewrite API responses.
- Pin client and server versions to a compatible response schema.
- Return explicit 204/no-body semantics only when the client expects them.
When it happens
Trigger: Server returning 2xx with empty body, HTML error page from a proxy, or a changed/non-JSON payload; gzip/encoding corruption; reqwest without the right features to decode the response content-type.
Common situations: API gateway or reverse proxy intercepting and returning HTML; server version mismatch after backend deploy changed the response schema; auth redirect returning a 2xx login page; misconfigured base URL pointing at the wrong service.
Understand the failure class
Background: "Invalid JSON response" and "Failed to parse response" errors: when an API answers 200 but the body isn't the JSON your library expected — this error's family across 28 libraries.
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Failed to parse part {} response: {}
- failed to build shared upload HTTP client
- default reqwest client builds
- failed to build shared HTTP client
- OIDC endpoint rejected request ({status}): {body}
AI-assisted analysis of xai-org/grok-build@bc7f02eddd (2026-08-31).
Data as JSON: /api/errors/6180a3d39cd8942a.
Report an issue: GitHub.