xai-org/grok-build · error

decoded artifact exceeds the {MAX_DECODED_BYTES}-byte cap

Error message

decoded artifact exceeds the {MAX_DECODED_BYTES}-byte cap

What it means

download_and_decode decodes a compressed artifact (e.g. gz/zstd) into the target binary. To prevent a decompression bomb from filling the disk, the decoder is capped with take(MAX_DECODED_BYTES + 1) (cap = 512 MiB). If more than MAX_DECODED_BYTES bytes are written, the function bails with this message. The compressed temp file is removed afterwards.

Source

Thrown at crates/codegen/xai-grok-update/src/auto_update.rs:1388

    let bin_tmp = tmp_download_path(dest);
    let (comp_in, bin_out) = (comp_tmp.clone(), bin_tmp.clone());
    let decoded = tokio::task::spawn_blocking(move || -> Result<()> {
        use std::io::Read as _;
        let src = std::fs::File::open(&comp_in)
            .with_context(|| format!("open compressed download {}", comp_in.display()))?;
        let decoder: Box<dyn std::io::Read> = match codec {
            Codec::Zstd => {
                Box::new(zstd::stream::read::Decoder::new(src).context("init zstd decoder")?)
            }
            Codec::Gzip => Box::new(flate2::read::GzDecoder::new(src)),
        };
        let mut out = std::fs::File::create(&bin_out)
            .with_context(|| format!("create decoded binary {}", bin_out.display()))?;
        let mut capped = decoder.take(MAX_DECODED_BYTES + 1);
        let written = std::io::copy(&mut capped, &mut out).context("decode")?;
        if written > MAX_DECODED_BYTES {
            anyhow::bail!("decoded artifact exceeds the {MAX_DECODED_BYTES}-byte cap");
        }
        Ok(())
    })
    .await;
    let _ = tokio::fs::remove_file(&comp_tmp).await;

    match decoded {
        Ok(Ok(())) => publish_downloaded_artifact(&bin_tmp, dest).await,
        Ok(Err(e)) => {
            let _ = tokio::fs::remove_file(&bin_tmp).await;
            Err(e)
        }
        Err(e) => {
            let _ = tokio::fs::remove_file(&bin_tmp).await;
            Err(anyhow::anyhow!("decode task panicked: {e}"))
        }
    }
}

View on GitHub (pinned to bc7f02eddd)

Solutions

  1. Check the artifact size on the release/mirror and publish a correctly compressed binary under 512 MiB decoded.
  2. Re-download the compressed artifact — the source copy may be corrupted; compare its checksum/hash if published.
  3. Ensure the right codec is used for the file extension (do not gunzip a non-gzip artifact).
  4. If you legitimately need larger binaries, raise MAX_DECODED_BYTES in auto_update.rs (currently 512 MiB).
  5. Verify the publisher did not accidentally ship a debug/unstripped build inflating the decoded size.

Example fix

// before: accepting any size, risking disk exhaustion
let mut out = std::fs::File::create(&bin_out)?;
std::io::copy(&mut decoder, &mut out).context("decode")?;

// after: the library's capped decode (already implemented)
const MAX_DECODED_BYTES: u64 = 512 * 1024 * 1024;
let mut capped = decoder.take(MAX_DECODED_BYTES + 1);
let written = std::io::copy(&mut capped, &mut out).context("decode")?;
if written > MAX_DECODED_BYTES {
    anyhow::bail!("decoded artifact exceeds the {MAX_DECODED_BYTES}-byte cap");
}
Defensive patterns

Strategy: validation

Validate before calling

// Validate the compressed artifact's plausible expanded size before decoding
const MAX_DECODED_BYTES: u64 = 512 * 1024 * 1024;
let comp_len = std::fs::metadata(&comp_tmp)?.len();
// gzip ratio is rarely better than ~1000:1 for real binaries; reject absurd inputs early
if comp_len == 0 || comp_len > MAX_DECODED_BYTES {
    anyhow::bail!("artifact size {} implausible for decoding", comp_len);
}

Type guard

fn within_decoded_cap(written: u64, cap: u64) -> bool {
    written <= cap
}

Try / catch

match download_and_decode(&comp_tmp, &bin_out).await {
    Ok(()) => {}
    Err(e) if e.to_string().contains("byte cap") => {
        eprintln!("artifact exceeds 512 MiB decode cap; verify you fetched the official release");
        std::fs::remove_file(&comp_tmp).ok();
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling download_and_decode / download_cli_artifact_from_gcs with an artifact whose decompressed size exceeds 512 MiB (512 * 1024 * 1024 bytes) — either a genuinely oversized binary or corrupt/hostile compressed data that expands far beyond the compressed size.

Common situations: A release pipeline accidentally publishes an uncompressed or debug-build artifact; a corrupted/truncated download confuses the decoder into producing garbage bytes; a malicious or compromised mirror serves a decompression bomb; a codec mismatch (decoding a plain file as compressed).

Related errors


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