sgl-project/sglang · error · ValueError

content hash mismatch for media_data[{index}]: expected {cal

Error message

content hash mismatch for media_data[{index}]: expected {caller_hash}, got {snapshot.content_digest}

What it means

After asynchronously loading a media snapshot, prepare_media_artifacts compares the snapshot's content_digest with the caller-supplied hash for that index. A mismatch means the underlying media content changed (or the hash was computed over different bytes), so the cached artifact would be stale/incorrect and the run is aborted.

Source

Thrown at python/sglang/srt/multimodal/media_artifacts/base.py:336

                    allow_featureless=allow_featureless,
                )
                if artifact is not None:
                    artifacts[index] = artifact
                    continue
            load_indices.append(index)

        # 2. read cache: build artifact key from media snapshot then try reading cache
        snapshot_futures = {
            index: self.io_executor.submit(
                self.snapshot_media_source, media_data[index], modality
            )
            for index in load_indices
        }
        for index, future in snapshot_futures.items():
            snapshot = await asyncio.wrap_future(future)
            caller_hash = content_hashes[index]
            if caller_hash is not None and caller_hash != snapshot.content_digest:
                raise ValueError(
                    f"content hash mismatch for media_data[{index}]: "
                    f"expected {caller_hash}, got {snapshot.content_digest}"
                )
            snapshots[index] = snapshot
            key = self._artifact_key(
                snapshot.content_digest, media_data[index], modality=modality
            )
            keys[index] = key
            artifacts[index] = self._get_cached_artifact(
                key,
                snapshot.content_digest,
                modality,
                allow_featureless=featureless_hit_mask[index],
            )

        # 3. deduplicate misses before decode
        first_index_by_key: dict[str, int] = {}
        previous_metadata: dict[str, MediaArtifact] = {}

View on GitHub (pinned to 0132848349)

Solutions

  1. Recompute the content hash from the exact bytes being loaded and pass the fresh value
  2. If the media is legitimately updated, treat it as a new item: new hash, new cache entry
  3. Verify both sides use the same digest function (parse_content_hash's scheme) and same byte payload (no re-encoding)

Example fix

// before
hashes = [old_hash_for_url]  # url content changed since
await prepare_media_artifacts(media, content_hashes=hashes, ...)
// after
hashes = [sha256(fetch_bytes(url)).hexdigest() for url in media]
await prepare_media_artifacts(media, content_hashes=hashes, ...)
Defensive patterns

Strategy: try-catch

Validate before calling

digest = sha256(load_bytes(item)).hexdigest()
# pass digest as the content hash so it matches the snapshot by construction

Try / catch

try:
    await prepare_media_artifacts(media, content_hashes=hashes, ...)
except ValueError as e:
    if "content hash mismatch" in str(e):
        hashes = [compute_hash(m) for m in media]  # refresh and retry once
        await prepare_media_artifacts(media, content_hashes=hashes, ...)
    else:
        raise

Prevention

When it happens

Trigger: Supplying mm_content_hashes[i] that doesn't equal the digest of the actually loaded media_data[i] — e.g. a URL whose content was updated, a mutated local file, or a hash computed with a different algorithm/normalization.

Common situations: Mutable object-store URLs behind a CDN; hashing the prompt text instead of image bytes; using a stale hash cached from a previous version of the asset; cross-process hash algorithm drift (e.g. blake2 vs sha256).

Related errors


AI-assisted analysis of sgl-project/sglang@0132848349 (2026-08-28). Data as JSON: /api/errors/6ae55ddfa485b44b. Report an issue: GitHub.