Michael Hospedales

Software engineer / Miami, FL

Writing

Field note · vLLM

IndexError in the multimodal processor when vLLM initializes Mistral Small 4

A change to how multimodal processors handle token inputs crashes Pixtral-architecture models during dummy-input construction, before the server ever accepts a request.

Hardware
NVIDIA DGX Spark · GB10 (SM121) · aarch64
CUDA
13.0
Driver
580.142
Software
vLLM 0.18.1rc1.dev171+g9c3ae04bf (main)
IndexError: list index out of range

Symptom#

Serving mistralai/Mistral-Small-4-119B-2603-NVFP4, the server never gets as far as accepting a request. It crashes during initialization, while vLLM is building a dummy multimodal input to size its encoder budget:

File "/usr/local/lib/python3.12/dist-packages/vllm/v1/engine/async_llm.py", line 143, in __init__
    self.input_processor = InputProcessor(self.vllm_config, renderer)
File "/usr/local/lib/python3.12/dist-packages/vllm/v1/engine/input_processor.py", line 61, in __init__
    mm_budget = MultiModalBudget(vllm_config, mm_registry)
File "/usr/local/lib/python3.12/dist-packages/vllm/multimodal/encoder_budget.py", line 87, in __init__
    all_mm_max_toks_per_item = get_mm_max_toks_per_item(
File "/usr/local/lib/python3.12/dist-packages/vllm/multimodal/encoder_budget.py", line 32, in get_mm_max_toks_per_item
    mm_inputs = mm_registry.get_dummy_mm_inputs(
File "/usr/local/lib/python3.12/dist-packages/vllm/multimodal/registry.py", line 240, in get_dummy_mm_inputs
    mm_inputs = processor.apply(
File "/usr/local/lib/python3.12/dist-packages/vllm/multimodal/processing/processor.py", line 1685, in apply
    ) = self._cached_apply_hf_processor(inputs, timing_ctx)
File "/usr/local/lib/python3.12/dist-packages/vllm/model_executor/models/pixtral.py", line 277, in _cached_apply_hf_processor
    prompt_ids, mm_info, _ = super()._cached_apply_hf_processor(inputs, timing_ctx)
File "/usr/local/lib/python3.12/dist-packages/vllm/multimodal/processing/processor.py", line 1496, in _cached_apply_hf_processor
    mm_kwargs, mm_prompt_updates = self._merge_mm_kwargs(
File "/usr/local/lib/python3.12/dist-packages/vllm/multimodal/processing/processor.py", line 1374, in _merge_mm_kwargs
    missing_kwargs_item = missing_kwargs[missing_next_idx]

Pixtral reaches that point through its own override of _cached_apply_hf_processor (pixtral.py:277) before landing in the shared _merge_mm_kwargs — which is why this is specific to the Pixtral architecture, not every multimodal model vLLM supports.

Root cause#

Introduced by commit 502c41a8f, "[Model] Use helper function to run MM processors with token inputs (where applicable)" (PR #38018). That change altered how multimodal processors handle token inputs, and the Pixtral architecture — the vision-language architecture behind Mistral Small 4 — crashes while computing dummy multimodal inputs during initialization, before any real request is processed. The commit immediately before it, 290809456, works fine with this model.

Fix#

Revert the regression:

git revert 502c41a8f

This is not a DGX Spark problem. The crash happens during model initialization, in shared multimodal-processing code, before any hardware-specific path is reached — it likely affects every Pixtral or Mistral Small 4 deployment running this vLLM revision, regardless of hardware. If you're hitting an IndexError at _merge_mm_kwargs during vLLM init on a Pixtral-family model, checking whether your build includes 502c41a8f is worth doing before looking anywhere else.

Status
upstream
First seen
March 26, 2026

Upstream issue or pull request

Have a thought about this?

Questions, corrections, and your own experience are welcome. Reply by email

All writing
  • Essay

    The cache hit that answered the wrong question

    I turned prefix caching back on for a 125B hybrid model on a DGX Spark, with the fixes carried from five open pull requests. Hits landed, a number planted deep in the prompt came back exactly every time, and an 11,000-token prompt dropped from 5.99 s to 0.96 s. Then one request answered the question two other requests were asking. Proving that was not a leak took a better instrument than the one I started with.

  • Field note

    Detecting which inference engine owns a port: vLLM vs. llama.cpp

    Detection that infers the engine from the port number breaks the moment either engine moves. Moving llama.cpp onto the port normally used by vLLM mislabeled it, and downstream code silently wrote null. /props is a clean discriminator: llama-server serves it, and the vLLM OpenAI-compatible server has no such route and returns 404. A second gotcha in the same detour: docker ps --filter publish= does not match a container using host networking.