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

  1. Log the raw body for the failing part number to identify what the server returned.
  2. Verify proxy/load-balancer health for the multipart endpoint route.
  3. Align client/server versions so MultipartUploadPartResponse matches the real payload.
  4. 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

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.

Related errors


AI-assisted analysis of xai-org/grok-build@bc7f02eddd (2026-08-31). Data as JSON: /api/errors/b956eacc1a905b6e. Report an issue: GitHub.