jdx/mise · error
remote cache blob pack has an invalid content type
Error message
remote cache blob pack has an invalid content type
What it means
Thrown on a blob-pack download (crates/mise-cache-core/src/lib.rs:640): the response's Content-Type media type (taken before any ';' parameter, trimmed) is not exactly BLOB_PACK_MEDIA_TYPE = "application/vnd.mise.cache-blob-pack.v1". The check guards decode_blob_pack from consuming a body that is not actually the framed pack format.
Source
Thrown at crates/mise-cache-core/src/lib.rs:640
.send()
.await?;
if matches!(
response.status(),
StatusCode::NOT_FOUND
| StatusCode::METHOD_NOT_ALLOWED
| StatusCode::NOT_IMPLEMENTED
) {
return Ok(None);
}
let response = response.error_for_status()?;
let media_type = response
.headers()
.get(CONTENT_TYPE)
.and_then(|value| value.to_str().ok())
.and_then(|value| value.split(';').next())
.map(str::trim);
if media_type != Some(BLOB_PACK_MEDIA_TYPE) {
bail!("remote cache blob pack has an invalid content type");
}
Ok(Some(
decode_blob_pack(response, digests, staging_dir).await?,
))
});
tokio::time::timeout(download_timeout, download)
.await
.map_err(|_| eyre!("remote cache blob pack download timed out for {url}"))?
}
pub async fn get_action_result(
&self,
action: &CacheDigest,
) -> Result<Option<RemoteActionResult>> {
let url = self.action_result_endpoint(action)?;
let result = retry_async("GET", &url, self.retries, || async {
let response = self
.request(reqwest::Method::GET, url.clone(), ACTION_RESULT_MEDIA_TYPE)View on GitHub (pinned to 6f52dcdf99)
Solutions
- Verify the server sets Content-Type: application/vnd.mise.cache-blob-pack.v1 on pack responses (parameters after ';' are tolerated, the media type itself is not)
- Check for proxies/gateways stripping or defaulting the header; add an exception for the pack route
- Confirm the pack feature is actually implemented server-side — if the endpoint is a stub returning JSON, disable blob packs client-side
- Upgrade the server to a version matching the v1 pack media type
Defensive patterns
Strategy: validation
Validate before calling
// server-side, before returning a pack: assert_eq!(response.content_type(), "application/vnd.mise.cache-blob-pack.v1"); // client-side preflight: check capabilities/features before requesting packs
Try / catch
match client.get_blob_pack(&digests, &staging).await {
Err(e) if e.to_string().contains("invalid content type") => {
client.disable_blob_packs();
fallback_per_blob(&client, &digests)
}
other => other?,
} Prevention
- Set the exact vendor media type on pack routes; do not rely on framework defaults
- Add proxy exceptions so Content-Type is preserved on cache routes
- Treat any content-type failure as a signal to fall back to per-blob downloads, which work regardless
When it happens
Trigger: Calling the blob-pack GET path (the download closure around lib.rs:620-660) against a server that responds with e.g. application/octet-stream, application/json (an error body that still returned 200), text/plain, or the correct type with a typo. Also triggered by intermediaries that rewrite Content-Type.
Common situations: A reverse proxy defaulting the type on unmapped extensions; a server framework that does not set vendor media types; version skew where an older server predates the vendor type; an HTML error page from a gateway returned with 200 after error_for_status passed.
Related errors
- action prediction payload is too large
- task action manifest has an invalid identity
- task action manifest contains duplicate predictions
- unsupported remote cache digest algorithm
- invalid remote cache digest
AI-assisted analysis of jdx/mise@6f52dcdf99 (2026-08-22).
Data as JSON: /api/errors/43dfa84444234864.
Report an issue: GitHub.