xai-org/grok-build · error
response missing Content-Length
Error message
response missing Content-Length
What it means
try_parallel_download first issues a HEAD request to learn the file size and validate that parallel range downloads are worthwhile. If the successful HEAD response carries no Content-Length header, the size is unknown and this error is thrown because chunked range downloads cannot be planned without it.
Source
Thrown at crates/codegen/xai-grok-update/src/auto_update.rs:1105
/// Try a parallel byte-range download to `dest`. Returns Err if the server
/// doesn't advertise a Content-Length, the file is too small to be worth
/// splitting, the range request is rejected, or any chunk transfer fails.
/// The caller is expected to fall back to a single-connection download on Err.
async fn try_parallel_download(
url: &str,
dest: &std::path::Path,
with_progress: bool,
) -> Result<()> {
let client = download_client()?;
let head = client.head(url).send().await?;
if !head.status().is_success() {
anyhow::bail!("HEAD failed: HTTP {}", head.status());
}
let size = head
.content_length()
.ok_or_else(|| anyhow::anyhow!("response missing Content-Length"))?;
if size < PARALLEL_DOWNLOAD_MIN_BYTES {
anyhow::bail!("file too small for parallel download ({} bytes)", size);
}
let n_chunks = parallel_chunk_count(size);
if n_chunks < 2 {
anyhow::bail!(
"file size yields {} chunk(s); not worth parallelizing",
n_chunks
);
}
let chunk_size = size.div_ceil(n_chunks);
let pb = if with_progress {
let pb = ProgressBar::new(size);
pb.set_style(
ProgressStyle::default_bar()
.template(" {bar:30.cyan/dim} {bytes}/{total_bytes} ({eta})")View on GitHub (pinned to bc7f02eddd)
Solutions
- Fall back to the non-parallel single-stream download path when Content-Length is missing
- Verify with `curl -I <url>` whether the server returns Content-Length on HEAD
- Bypass or reconfigure the proxy/CDN that is stripping the header
- Point the download at the canonical artifact URL/mirror that serves proper HEAD metadata
Example fix
// before
let size = head.content_length()
.ok_or_else(|| anyhow::anyhow!("response missing Content-Length"))?;
// after
match head.content_length() {
Some(size) if size >= PARALLEL_DOWNLOAD_MIN_BYTES => download_parallel(url, size).await,
_ => download_single_stream(url).await, // graceful fallback
} Defensive patterns
Strategy: fallback
Validate before calling
let head = client.head(url).send().await?;
let has_len = head.content_length().is_some();
if !has_len { eprintln!("server omitted Content-Length; use single-stream download"); } Type guard
fn supports_parallel_download(head: &reqwest::Response) -> bool {
head.status().is_success() && head.content_length().map_or(false, |n| n >= PARALLEL_DOWNLOAD_MIN_BYTES)
} Try / catch
match download_with_progress(url, &dest).await {
Err(e) if e.to_string().contains("response missing Content-Length") => {
download_single_stream(url, &dest).await?; // fallback
}
other => other,
} Prevention
- Test artifact URLs with `curl -I` to confirm Content-Length on HEAD
- Avoid proxies/CDNs that strip HEAD metadata
- Always implement a single-stream fallback for downloads
- Prefer mirrors known to serve proper HEAD responses
When it happens
Trigger: Calling download_with_progress / download_silent against a server whose HEAD response for the artifact URL omits Content-Length — e.g. chunked transfer encoding, compression middleware, or a CDN rewriting HEAD responses.
Common situations: Downloading through a reverse proxy or CDN that strips/omits Content-Length on HEAD; servers that respond 200 with chunked encoding instead of a length; enterprise proxies that transform responses; misconfigured artifact mirror.
Related errors
- GCS download failed: {}
- Download failed: HTTP {}
- send failed: {body}
- screen query failed: {body}
- resize failed: {body}
AI-assisted analysis of xai-org/grok-build@bc7f02eddd (2026-08-31).
Data as JSON: /api/errors/86af78384daf8379.
Report an issue: GitHub.