xai-org/grok-build · error
Failed to parse part {} response: {}
Error message
Failed to parse part {} response: {} What it means
During multipart part upload, a 2xx response body must decode into MultipartUploadPartResponse; when reqwest's response.json() fails, this error names the failing part number and the parse error. The part bytes reached the server, but the part acknowledgement could not be parsed, so the multipart state cannot be advanced safely.
Source
Thrown at crates/codegen/xai-file-utils/src/storage_client.rs:2018
.header("Content-Length", length.to_string());
for (name, value) in crate::trace_context::trace_context_headers().iter() {
request = request.header(name.clone(), value.clone());
}
match request.body(body).send().await {
Ok(response) => {
tracing::debug!(
"Part {} HTTP response received in {:?}, status={}",
part_number,
send_start.elapsed(),
response.status()
);
if response.status().is_success() {
let parse_start = std::time::Instant::now();
let part_response: MultipartUploadPartResponse =
response.json().await.map_err(|e| {
anyhow::anyhow!("Failed to parse part {} response: {}", part_number, e)
})?;
tracing::debug!(
"Part {} response parsed in {:?}",
part_number,
parse_start.elapsed()
);
return Ok(part_response);
}
let check = ResponseCheck::from_response(response, &operation).await;
if check.is_retryable && attempt < retry_config.max_retries {
check.wait_for_retry(retry_config, attempt).await;
attempt += 1;
continue;
}
return Err(HttpUploadError {
status_code: check.status_code,
message: check.message,View on GitHub (pinned to bc7f02eddd)
Solutions
- Log the raw body for the failing part number to identify what the server returned.
- Verify proxy/load-balancer health for the multipart endpoint route.
- Align client/server versions so MultipartUploadPartResponse matches the real payload.
- Retry the specific part upload once the response path is fixed.
Example fix
// before
let part_response: MultipartUploadPartResponse = response.json().await
.map_err(|e| anyhow::anyhow!("Failed to parse part {} response: {}", part_number, e))?;
// after
let text = response.text().await?;
let part_response: MultipartUploadPartResponse = serde_json::from_str(&text)
.map_err(|e| anyhow::anyhow!("Failed to parse part {} response: {} (body: {:.200})", part_number, e, text))?; Defensive patterns
Strategy: try-catch
Validate before calling
// Ensure the multipart endpoint answers JSON before starting part uploads
let probe = reqwest::Client::new().post(multipart_start_url).send().await?;
if !probe.headers().get(reqwest::header::CONTENT_TYPE)
.map(|v| v.to_str().unwrap_or_default().contains("json")).unwrap_or(false) {
anyhow::bail!("multipart endpoint not returning JSON; check proxy/route");
} Try / catch
match client.upload_part(part_number, bytes, upload_id).await {
Ok(resp) => record_part(resp),
Err(e) if e.to_string().starts_with("Failed to parse part") => {
let part = extract_part_number(&e.to_string());
tracing::error!("part {part} got non-JSON ack: {e:#}; retrying that part");
}
Err(e) => return Err(e),
} Prevention
- Keep multipart response schemas covered by client/server contract tests.
- Configure proxies/LBs to not intercept the multipart routes.
- Handle per-part retries idempotently so a failed parse can be re-sent.
- Log raw bodies for part responses in debug mode to speed diagnosis.
When it happens
Trigger: Part upload returning 200 with empty/HTML/garbage body (proxy interference), backend response schema drift, or truncated response due to connection issues after headers were sent.
Common situations: Reverse proxies timing out mid-response and emitting partial/HTML bodies; version mismatch between client expectations and server part-response format; load balancer error pages returned with 2xx-adjacent statuses.
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 upload response: {}
- default reqwest client builds
- failed to build shared HTTP client
- failed to build shared upload HTTP client
- Task panicked: {}
AI-assisted analysis of xai-org/grok-build@bc7f02eddd (2026-08-31).
Data as JSON: /api/errors/b956eacc1a905b6e.
Report an issue: GitHub.