jdx/mise · error

remote cache blob pack content length metadata mismatch: exp

Error message

remote cache blob pack content length metadata mismatch: expected {}, decoded {}

What it means

Thrown while validating a blob-pack download (crates/mise-cache-core/src/lib.rs:321): the response carried an X-style blob-pack metadata header-derived content_length (from the Content-Length-style optional header parsed in from_headers), and it does not equal decoded.framed_bytes — the number of bytes actually decoded from the framed pack stream (magic + per-blob records). This is an integrity check that the server's declared size matches the body it sent.

Source

Thrown at crates/mise-cache-core/src/lib.rs:321

    blob_count: u64,
    payload_bytes: u64,
    framed_bytes: u64,
}

impl BlobPackResponseMetadata {
    fn from_headers(headers: &HeaderMap) -> Result<Self> {
        Ok(Self {
            content_length: optional_u64_header(headers, CONTENT_LENGTH.as_str())?,
            blob_count: optional_u64_header(headers, BLOB_PACK_BLOBS_HEADER)?,
            payload_bytes: optional_u64_header(headers, BLOB_PACK_BYTES_HEADER)?,
        })
    }

    fn validate(self, decoded: BlobPackResponseStats) -> Result<BlobPackResponseStats> {
        if let Some(content_length) = self.content_length
            && content_length != decoded.framed_bytes
        {
            bail!(
                "remote cache blob pack content length metadata mismatch: expected {}, decoded {}",
                content_length,
                decoded.framed_bytes
            );
        }
        if let Some(blob_count) = self.blob_count
            && blob_count != decoded.blob_count
        {
            bail!(
                "remote cache blob pack blob count metadata mismatch: expected {}, decoded {}",
                blob_count,
                decoded.blob_count
            );
        }
        if let Some(payload_bytes) = self.payload_bytes
            && payload_bytes != decoded.payload_bytes
        {
            bail!(

View on GitHub (pinned to 6f52dcdf99)

Solutions

  1. Retry the download once — a transient truncation (dropped connection mid-body) can produce this
  2. Disable blob packs for this remote (the client tracks blob_packs_disabled; falling back to per-blob GETs sidesteps pack metadata entirely) and verify blobs download individually
  3. Check any proxy/CDN between client and cache for body-rewriting (compression, chunked re-framing); bypass it or exclude the pack media type application/vnd.mise.cache-blob-pack.v1
  4. If you operate the server, ensure the metadata headers describe the exact framed payload emitted
Defensive patterns

Strategy: retry

Try / catch

match client.get_blob_pack(&digests, &staging).await {
    Err(e) if e.to_string().contains("content length metadata mismatch") => {
        client.disable_blob_packs();
        for d in &digests { let _ = client.get_blob(d, media_type).await?; } // per-blob fallback
    }
    other => other?,
}

Prevention

When it happens

Trigger: Calling the blob-pack download path (decode_blob_pack at lib.rs:899, fed by get_blob_pack) where the server advertises a content length in its headers that differs from the actual framed stream size — e.g. a proxy rewrote/truncated the body, the server has a bug computing the header, or a chunked/encoded response made the header stale.

Common situations: A corporate proxy or CDN re-encoding responses (gzip stripped or applied) so Content-Length no longer matches the decoded bytes; a misbehaving or incompatible remote cache server version; a race where the pack was regenerated server-side between header emission and body streaming.

Related errors


AI-assisted analysis of jdx/mise@6f52dcdf99 (2026-08-22). Data as JSON: /api/errors/80a47b48f1b97c34. Report an issue: GitHub.