sgl-project/sglang · error · ValueError
mm_content_hashes has {len(content_hashes)} entries for {med
Error message
mm_content_hashes has {len(content_hashes)} entries for {media_count} {modality.name.lower()} items What it means
prepare_media_artifacts requires the optional mm_content_hashes list to be exactly as long as media_data; a length mismatch means the caller's per-item content hashes cannot be aligned with the media items, so the artifact cache cannot be keyed safely.
Source
Thrown at python/sglang/srt/multimodal/media_artifacts/base.py:285
"""Try resolving one preprocess-cache artifact for each processor input.
Each media input is looked up independently, and results preserve the
input order. A cache hit returns the stored artifact (the cache item).
A miss snapshots and decodes the raw input, runs
``prepare_artifact_batch``, stores its cache-safe artifact, and returns
the prepared artifact to the current request. Duplicate and concurrent
misses share the same preprocessing work.
This stage is prompt-independent. It does not create prompt tokens,
offsets, or ``MultimodalDataItem`` objects; the model processor uses the
returned artifacts to compose those request-specific values afterward.
"""
modality = self._resolve_artifact_modality(modality)
media_count = len(media_data)
if content_hashes is None:
content_hashes = [None] * media_count
if len(content_hashes) != media_count:
raise ValueError(
f"mm_content_hashes has {len(content_hashes)} entries for "
f"{media_count} {modality.name.lower()} items"
)
content_hashes = [parse_content_hash(value) for value in content_hashes]
if featureless_hit_mask is None:
featureless_hit_mask = [False] * media_count
if len(featureless_hit_mask) != media_count:
raise ValueError("featureless_hit_mask must align with media_data")
# keep per-input state aligned for duplicates and partial hits
artifacts: list[Optional[MediaArtifact]] = [None] * media_count
snapshots: list[Optional[MediaSnapshot]] = [None] * media_count
keys: list[Optional[str]] = [None] * media_count
# 1. fast path: resolve trusted provided hash hits without reading media
# e.g., an image could be submitted with a provided hash:
# "image_url": {View on GitHub (pinned to 0132848349)
Solutions
- Regenerate content_hashes with one entry per item in the current media_data list (in the same order)
- If you don't have hashes, pass content_hashes=None instead of a partial list
- Log len(media_data) and len(content_hashes) upstream to find where they diverge
Example fix
// before hashes = [h for h, m in zip(prev_hashes, media) if m in new_set] # shorter than media await prepare_media_artifacts(media, content_hashes=hashes, ...) // after hashes = [compute_hash(m) for m in media] await prepare_media_artifacts(media, content_hashes=hashes, ...)
Defensive patterns
Strategy: validation
Validate before calling
assert content_hashes is None or len(content_hashes) == len(media_data), (len(content_hashes), len(media_data))
Prevention
- Always derive hashes with a list comprehension over the exact media_data list being passed
- Never reuse a hash list from a previous/different media list
When it happens
Trigger: Calling prepare_media_artifacts (via process_mm_data_async) with content_hashes shorter/longer than media_data — e.g. hashing only new items while resending the full media list, or vice versa.
Common situations: Incremental prefetch flows that compute hashes for a subset of images; EPD/speculative decoding paths where the hash list is built per-request but media_data is per-batch; races where media list is mutated between hash computation and the call.
Related errors
- Unsupported Kimi-K3 encoder media item: {image}
- Unsupported image type: {type(image)}
- When using multiple prompts with multiple input images, prov
- {key}.position_ids is required
- {key}.{field} is required
AI-assisted analysis of sgl-project/sglang@0132848349 (2026-08-28).
Data as JSON: /api/errors/55b61db548b01da6.
Report an issue: GitHub.