Field note · vLLM
FlashInfer CUTLASS MoE fails TMA descriptor init on SM121
FlashInfer ships a precompiled fused-MoE library built for SM120. Its TMA descriptors do not initialize on SM121, so concurrent MoE batches crash after hours of clean operation. vLLM cannot patch it.
- Hardware
- NVIDIA DGX Spark · GB10 (SM121) · aarch64
- CUDA
- 13.0
- Software
- vLLM 0.18.1rc1.dev223+g3d6b06a27 (spark-fixes)
[TensorRT-LLM][ERROR] Assertion failed: Failed to initialize cutlass TMA WS grouped gemm. Error: Error InternalSymptom
The day after fixing the FP8 arch-guard trap,
the same model — mistralai/Mistral-Small-4-119B-2603-NVFP4 — ran clean for a long time and
then died a different way. The server had been up since roughly 05:32 UTC and handled traffic
without issue for about four and a half hours before crashing at 10:08 UTC, mid-MoE-forward
pass, on a request with 36,308 computed tokens and a single output token.
It didn't crash without warning. The lead-up shows repeated TMA descriptor initialization failures:
Error: Failed to initialize the TMA descriptor 715
This is a different subsystem from the FP8 scaled-mm trap — this failure is in the fused-MoE
grouped-GEMM path, on a server whose MoE backend had resolved to FLASHINFER_CUTLASS.
Root cause
FlashInfer's fused-MoE kernels are JIT-compiled the first time they're needed and cached on
disk as fused_moe_120.so, under ~/.cache/flashinfer/jit_cache/. The 120 in that filename
is the tell: the kernel templates behind it target cutlass::arch::Sm120. Dispatch happens
through get_cutlass_fused_moe_module(device_arch), and on SM121 that function maps straight
onto the SM120 module — there's no separate SM121 build to fall back to. That would be fine if
the two architectures agreed on everything relevant. They don't: the TMA descriptor format
differs between SM120 and SM121, and the SM120 module's descriptors fail to initialize against
real SM121 hardware.
Two things narrow this down further, without fully explaining it. Sequential requests are
fine — only concurrent batches trigger the failure, and neither investigation pins down why.
And NVIDIA's own DGX Spark NVFP4 fix (PR #38423, commit b4a2f3ac3) does not resolve it. That
patch changed quant_scales = None to quant_scales = [] and improved kernel detection on
the vLLM side — a real fix for what it targets — but the crash survives it unchanged, because
the fault was never in vLLM's dispatch logic. It's baked into a .so FlashInfer already built
for the wrong chip. vLLM can change every line of its own source and this still crashes, since
vLLM never gets a chance to generate the kernel in the first place.
Fix
The working option for this model was --moe-backend cutlass — vLLM's own CUTLASS kernels,
compiled from source with 12.1a, instead of FlashInfer's precompiled 120 build. That held
for 9+ hours under load. Two backends to avoid for this specific failure: marlin (FP4→FP16
decompression — very slow) and flashinfer_cutlass / auto (the same TMA crash).
That is specific to this model, not a general SM121 answer — NVIDIA's own DGX Spark guidance
points at marlin, and a different NVFP4 MoE model needed a completely different setting to
get stable. Before copying this flag onto anything other than Mistral Small 4, see the
follow-up on which MoE backend actually works.