Hmbown/CodeWhale · error

download {url} exceeds compressed size cap of {compressed_ca

Error message

download {url} exceeds compressed size cap of {compressed_cap} bytes

What it means

download_with_cap enforces a soft compressed-size cap of 4x the configured max_size on the bytes actually read; the unpack step separately enforces max_size on uncompressed bytes. A body over the cap bails with the limit in the message. The cap exists to bound memory before decompressing payloads that could expand enormously.

Source

Thrown at crates/tui/src/skills/install.rs:1166

        .send()
        .await
        .with_context(|| format!("failed to GET {url}"))?;
    let status = resp.status();
    if !status.is_success() {
        if status == reqwest::StatusCode::NOT_FOUND {
            return Ok(DownloadAttempt::NotFound(status));
        }
        bail!("download {url} returned {status}");
    }
    // Soft cap on the *compressed* download — well above max_size to allow
    // for highly compressible payloads but still bounded.
    let compressed_cap = max_size.saturating_mul(4);
    let bytes = resp
        .bytes()
        .await
        .with_context(|| format!("failed to read body of {url}"))?;
    if (bytes.len() as u64) > compressed_cap {
        bail!("download {url} exceeds compressed size cap of {compressed_cap} bytes");
    }
    Ok(DownloadAttempt::Bytes(bytes.to_vec()))
}

struct StagedSkill {
    skill_name: String,
    staged_path: PathBuf,
}

/// Validate a tarball and extract it into `<skills_dir>/<name>.tmp/`.
fn stage_tarball(bytes: &[u8], skills_dir: &Path, max_size: u64) -> Result<StagedSkill> {
    fs::create_dir_all(skills_dir)
        .with_context(|| format!("failed to create skills directory {}", skills_dir.display()))?;

    // Two passes: first determine the skill name (and therefore the staged
    // dir) by finding the SKILL.md, then extract under that staged dir.
    // Both passes share the same archive bytes; we reset by wrapping fresh
    // decoders.

View on GitHub (pinned to 0c42157ee5)

Solutions

  1. Raise the skill max-size configuration if the artifact is legitimately large.
  2. Point the install at a slimmer artifact: a release tarball or subpath export rather than the full repo archive.
  3. If the size is unexpected, inspect the URL; a redirect to an HTML page or wrong artifact can inflate it.
  4. Report oversized skills upstream so the canonical artifact stays under limits.

Example fix

# before: limit 10 MiB, artifact 45 MiB compressed
/skill install github:owner/big-repo

# after: install the slim release tarball
/skill install https://github.com/owner/big-repo/releases/download/v1/pack.tar.gz
Defensive patterns

Strategy: fallback

Validate before calling

// HEAD pre-check against the same 4x compressed cap used at download time
let resp = reqwest_client().head(url).send().await?;
if let Some(len) = resp
    .headers()
    .get(reqwest::header::CONTENT_LENGTH)
    .and_then(|v| v.to_str().ok())
    .and_then(|v| v.parse::<u64>().ok())
{
    if len > max_size.saturating_mul(4) {
        eprintln!("artifact is {len} bytes, above the compressed cap; pick a slimmer source");
    }
}

Try / catch

match fetch_tarball(&source, &network, max_size).await {
    Err(err) if err.to_string().contains("exceeds compressed size cap") => {
        // fallback: install a slimmer release artifact or raise the configured limit
    }
    other => other?,
}

Prevention

When it happens

Trigger: Installing a skill tarball whose compressed size exceeds 4x the configured skill size limit (e.g. a 10 MiB limit rejecting anything above ~40 MiB compressed), or a misdirected URL serving a huge file such as a full repo archive with vendored dependencies.

Common situations: Community skills bundling binaries or media, monorepo archives grabbed whole by the github: shorthand, and locally lowered limits on constrained machines.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@0c42157ee5 (2026-08-20). Data as JSON: /api/errors/3eb278316d3e42ee. Report an issue: GitHub.