At a glance
ProblemThe vLLM container crashes on startup during NCCL initialisation and never serves a request. Occurs only when the model is spread across more than one GPU.
AffectsvLLM served on NVIDIA mediated vGPU (a virtual machine with vGPU profiles, rather than passthrough or bare metal), with tensor parallelism greater than 1
WorkaroundNone that keeps both the newer image and multi-GPU. Stay on the previously working image, or run single-GPU if the model fits.
SolutionEnable UVM on each vGPU in the virtual machine's advanced parameters (pciPassthru<vgpu-id>.cfg.enable_uvm = 1). Hypervisor-side change, requires a VM power-off, and disables vMotion for that VM.

Problem

After moving to a newer vLLM image, the inference pod enters a crash loop. It fails during startup, while NCCL is setting up communication between the GPUs — so the model never finishes loading and the server never accepts a request.

Every tensor-parallel worker dies with the same error. The failure of the engine core then brings down the API server process, so the pod exits rather than degrading.

[<timestamp>] NCCL version 2.27.5+cuda12.9, cudaDriverVersion 13000
[<timestamp>] init.cc:426 NCCL WARN Cuda failure 'operation not supported'
[<timestamp>] ncclCommInitRank failed: unhandled cuda error
[<timestamp>] RuntimeError: NCCL error: unhandled cuda error
[<timestamp>] EngineCore failed to start
[<timestamp>] APIServer exiting

The block above is abridged and reformatted — the exact wording varies with the vLLM and NCCL versions in your image. The line that identifies this issue is Cuda failure 'operation not supported' raised at NCCL initialisation (ncclCommInitRank).

Rule this out first

This is a startup failure. vLLM never reaches the point of serving traffic.

If your pod starts successfully and then fails later — timeouts, stalled requests, or errors that appear only under load — that is a different problem with a different cause, and this article does not apply. Check whether the pod ever reported the server as ready before going further.

Affected versions

ProductEnterprise h2oGPTe deployments that serve models through the bundled vLLM container. The same failure occurs with vLLM run standalone, and with plain PyTorch using the NCCL backend.
ComponentvLLM 0.19.1 bundling NCCL 2.27.5+cuda12.9 has been confirmed affected. vLLM 0.8.5 is confirmed unaffected on the same host, the same driver and the same GPUs.
DeploymentNVIDIA mediated vGPU only. Confirmed on VMware vSphere / Tanzu; the same signature is reported on other hypervisors. Bare metal and full GPU passthrough are not affected.
TriggerTensor parallelism greater than 1 — that is, any NCCL communicator spanning two or more vGPUs. Single-GPU serving does not initialise NCCL and does not hit this.
Not a factorGPU model, NVLink, and driver version. See What this is not below — each of these has been tested and excluded.
Fixed inNot a product defect, and not resolved by upgrading the image. The fix is a virtual machine setting applied on the hypervisor — see Solution.

Cause

A mediated vGPU does not expose the same memory and peer-to-peer capabilities as a physical GPU. By default, the unified memory and peer addressing that NCCL relies on are not presented to the guest at all.

Running nvidia-smi -q inside the container on an affected host shows that plumbing stubbed out rather than merely restricted:

Addressing Mode : None
Peer Type       : N/A
Atomic Caps     : N/A

Newer NCCL releases require that capability when they build a communicator. When the driver reports it as unavailable, NCCL raises Cuda failure 'operation not supported' and aborts, instead of falling back to a transport that would work on this platform. Older NCCL releases did not take that path, which is why an older image continues to run on the identical host and driver.

The precise code path inside NCCL has not been isolated, and this article does not claim one. What is established is narrower and sufficient to act on: the capability is missing from the guest, the newer NCCL requires it, and supplying it resolves the crash.

What this is not

Three plausible explanations have been tested and ruled out. They are listed because each one costs time to chase:

TheoryStatus
The GPU driver or CUDA upgrade broke itRuled out. The older vLLM image runs a healthy multi-GPU job on the same upgraded driver, on the same node.
vGPU cannot do multi-GPU NCCL at allRuled out. Same evidence — a working multi-GPU NCCL job exists on the platform. It is this NCCL version that fails, not the platform.
Missing or unexposed NVLinkRuled out. The failure has been reproduced on hardware with no NVLink whatsoever, and observed on hosts where NVLink is fully exposed to the guest. NVLink is not the deciding factor.
Disabling the NCCL cuMem allocator with NCCL_CUMEM_ENABLE=0Tested, did not help. The crash is identical with and without it. It is widely suggested for similar-looking errors, so it is worth knowing it has already been tried here.

Workaround

No workaround keeps both the newer image and multi-GPU

There is no container environment variable, vLLM flag or Helm value that makes the newer image initialise NCCL on a vGPU without the host-side change. The options below avoid the crash by giving something up, and are interim measures only:

  • Stay on the last known-working image. If an older image served the same model successfully on this hardware, it will continue to do so — including on an upgraded driver. This is the safest hold while the VM change is scheduled, but it forecloses the newer models and fixes in the current image.
  • Run on a single GPU. Setting tensor parallelism to 1 avoids NCCL entirely. This only helps where the model and its context fit in one vGPU's frame buffer, so it is rarely an option for large models — a 70B-class model will not fit.

Neither is a fix. Both leave the deployment unable to serve a large model on the current image, which is usually the reason for upgrading in the first place.

Solution

Enable UVM on each vGPU in the VM's advanced parameters

The fix is applied to the virtual machine, by whoever administers your hypervisor — not inside the container, the pod spec or the Helm chart. On the VM's Advanced Parameters, set the following, once per vGPU assigned to the machine:

pciPassthru0.cfg.enable_uvm = 1
pciPassthru1.cfg.enable_uvm = 1

The index in pciPassthru<vgpu-id> identifies the vGPU. A VM with two vGPUs needs both lines, as shown; a VM with four needs four. Setting it on only some of the vGPUs leaves the communicator unable to form.

The virtual machine must be powered off for the parameter to be added, then powered back on. A reboot from inside the guest is not sufficient.

Once the VM is back up, redeploy the vLLM workload on the newer image with the original tensor-parallel setting. No container-side change is needed, and no NCCL environment variables have to be set.

Before you schedule this — it disables vMotion

Enabling this parameter turns off vSphere vMotion migration for that virtual machine. This is documented behaviour, not a side effect of our configuration.

Confirm your operational requirements can accommodate it before applying the change to production. If the affected VMs rely on live migration for host maintenance, patching or failover, that procedure has to be revisited first. The change is also disruptive to apply, because it requires a power-off.

The performance impact of enabling UVM on these workloads has not been measured, and this article makes no claim about it in either direction.

Where this is documented

The hypervisor vendor documents this parameter for deep-learning virtual machine classes — for example VMs running retrieval-augmented generation workloads or an inference server. It is not published as a blanket requirement for every AI workload, so you may not find it by searching for your own use case, and the failure it prevents is not named on that page.

Be aware of a wrinkle in the vendor's own text: it instructs you to set pciPassthru<vgpu-id>.cfg.enable_uvm, then shows an example written as pciPassthru0.cfg.parameter=1. The first form is the correct one. Use enable_uvm as written above.

How to verify

1. Confirm this is a mediated vGPU

Run inside the container, or in a pod on the affected node. If the mode is not a virtualised one, this article does not apply:

nvidia-smi -q | grep -i "Virtualization Mode"

2. Check the peer capability, before and after

This is the quickest confirmation that the change took effect. Capture it before applying the parameter and again after the VM is back up:

nvidia-smi -q | grep -Ei "Addressing Mode|Peer Type|Atomic Caps"

Values of None and N/A on an affected host are the signature described under Cause.

3. Test NCCL directly, before launching vLLM

A minimal collective is far faster to iterate on than a full model load, and it isolates the failure to NCCL rather than to vLLM. Save this inside the container as nccl_check.py:

import os
import torch
import torch.distributed as dist

dist.init_process_group("nccl")
torch.cuda.set_device(int(os.environ["LOCAL_RANK"]))
t = torch.ones(1024, device="cuda")
dist.all_reduce(t)
torch.cuda.synchronize()
print("rank", dist.get_rank(), "ok", t[0].item())

Run it across two GPUs:

torchrun --nproc_per_node=2 nccl_check.py

Before the fix this fails with the same Cuda failure 'operation not supported'. After the fix each rank prints ok 2.0.

4. Start the workload

  1. Redeploy vLLM on the newer image with the tensor-parallel setting you originally wanted.
  2. Confirm the pod reaches a ready state rather than crash-looping, and that the log shows the API server started.
  3. Send a real inference request and confirm a response. A pod that starts is necessary but not sufficient — this failure previously killed the server before it ever served one.

If this doesn't resolve it

Re-run the workload with NCCL_DEBUG=INFO set in the container. This produces the transport selection and initialisation detail needed to tell a remaining capability problem apart from an unrelated failure that shares the wording.

Then open a support ticket including:

  • The vLLM and NCCL versions in the image, and the versions of the last image that worked
  • Hypervisor and version, the vGPU profile in use, and the number of vGPUs on the VM
  • GPU driver and CUDA versions, in the guest and on the hypervisor host
  • Output of nvidia-smi, nvidia-smi -q and nvidia-smi topo -m from inside the container
  • Confirmation that enable_uvm is set for every vGPU on the VM, and that the VM was power-cycled afterwards
  • The NCCL_DEBUG=INFO log from a failing start
  • Whether the minimal NCCL test in step 3 passes or fails

Related