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
- Check the artifact size on the release/mirror and publish a correctly compressed binary under 512 MiB decoded.
- Re-download the compressed artifact — the source copy may be corrupted; compare its checksum/hash if published.
- Ensure the right codec is used for the file extension (do not gunzip a non-gzip artifact).
- If you legitimately need larger binaries, raise MAX_DECODED_BYTES in auto_update.rs (currently 512 MiB).
- 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
- Always decode with .take(cap + 1) so runaway decompression is bounded.
- Publish stripped, compressed release binaries and keep decoded size well under the cap.
- Verify published artifact checksums before decoding.
- Clean up temp files on failure (the function already removes comp_tmp).
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
- invalid worktree id from dest: {worktree_id}
- invalid worktree id {:?}
- invalid {GROK_CHAT_LOCAL_WORKSPACE_MODE_ENV}={other:?}; expe
- Error: --session-id must be a valid UUID (got '{session_id}'
- {CHAT_MODE_FORK_CONFLICT}
AI-assisted analysis of xai-org/grok-build@bc7f02eddd (2026-08-31).
Data as JSON: /api/errors/e0088004a8e8eda8.
Report an issue: GitHub.