Resolving the CUDA Toolkit Version Mismatch: Installing CUDA 13.0 nvcc for Blackwell SM120 Support
Introduction
In the complex ecosystem of large language model deployment on cutting-edge hardware, few problems are as frustrating as a version mismatch between software components that each independently detect system capabilities. Message 11443 captures a pivotal moment in this debugging journey: the successful resolution of a CUDA toolkit version mismatch that had been blocking the deployment of Kimi K2.6 with FlashInfer JIT compilation on Blackwell GPUs. This message represents the culmination of a multi-step diagnostic process where the assistant traced a cryptic error through FlashInfer's architecture detection logic, identified the root cause, attempted a clever but ultimately flawed workaround, and finally implemented the correct fix by installing a compatible CUDA toolkit version.
The Problem: SM120 Meets CUDA 12.8
The Blackwell RTX PRO 6000 GPUs in this deployment have a compute capability of SM120 (major=12, minor=0). FlashInfer, the JIT compilation library used by SGLang for sampling kernels, performs automatic CUDA architecture detection at import time. Its _normalize_cuda_arch method contains a guard that raises RuntimeError("SM 12.x requires CUDA >= 12.9") when it encounters SM120. This exception is caught during initialization, resulting in an empty TARGET_CUDA_ARCHS set, which later causes check_cuda_arch() to fail because no eligible architectures are found.
The root cause, as the assistant discovered through careful tracing in the preceding messages, is that FlashInfer's get_cuda_version() function queries the system nvcc binary to determine the CUDA toolkit version. The system had CUDA 12.8 installed at /usr/local/cuda-12.8, and nvcc reported version 12.8 — below the 12.9 threshold required for SM120 support. This persisted despite PyTorch being built with CUDA 13.0, because FlashInfer checks the actual toolkit, not the PyTorch runtime version.
The Failed Workaround: CUDA_HOME=/dev/null
The assistant's first attempted fix was elegant in theory but destructive in practice. By setting CUDA_HOME=/dev/null in the systemd service files, the assistant hoped to make FlashInfer's get_cuda_path() fail gracefully, causing it to fall back to torch.version.cuda, which reports 13.0. This would bypass the version check entirely.
However, this approach failed catastrophically. As the assistant realized in its reasoning: "Right, /dev/null/bin/nvcc doesn't exist. CUDA_HOME=/dev/null was too aggressive — the JIT kernel compilation also uses CUDA_HOME to find nvcc." The service crashed because SGLang's own JIT kernel compilation (using TVM/Triton) also needs a working nvcc binary. Setting CUDA_HOME to a nonexistent path broke all compilation, not just the version detection.
This failure taught an important lesson: the CUDA toolkit serves dual purposes in this environment. It provides both the runtime libraries needed for execution and the compiler toolchain (nvcc) needed for JIT compilation. Any fix must preserve access to a working nvcc while ensuring the detected version satisfies FlashInfer's SM120 requirement.
The Correct Fix: Installing CUDA 13.0 nvcc
Message 11443 executes the correct fix. The assistant has already installed cuda-nvcc-13-0 via apt-get install in the preceding message (11442), leveraging the system's existing CUDA repository configuration which already had packages for versions 12.9 and 13.2 available. Now it performs the integration work.
The message contains a single bash command executed over SSH to the remote host at 10.1.2.200. Let us examine each step in detail.
Step 1: Verification
ls /usr/local/cuda-13.0/bin/nvcc
/usr/local/cuda-13.0/bin/nvcc --version 2>&1 | tail -2
The assistant first verifies that the installation succeeded by checking for the nvcc binary at the expected path and confirming its version. The output confirms: Cuda compilation tools, release 13.0, V13.0.88. This is the critical piece — CUDA 13.0 satisfies the >= 12.9 requirement that FlashInfer enforces for SM120 support.
Step 2: Service Configuration Updates
sed -i '/^Environment=OMP_NUM_THREADS/a Environment=CUDA_HOME=/usr/local/cuda-13.0' /etc/systemd/system/sglang-k26.service
sed -i '/^Environment=OMP_NUM_THREADS/a Environment=CUDA_HOME=/usr/local/cuda-13.0' /etc/systemd/system/sglang-k26-eagle3.service
The assistant updates both systemd service files — the autoregressive K2.6 service and the EAGLE-3 speculative decoding service — to set CUDA_HOME to the newly installed CUDA 13.0 toolkit. The sed command appends the environment variable after the line matching Environment=OMP_NUM_THREADS, ensuring it appears in the correct section of the service file.
sed -i 's|PATH=/root/venv_sglang211/bin:|PATH=/usr/local/cuda-13.0/bin:/root/venv_sglang211/bin:|' /etc/systemd/system/sglang-k26.service
sed -i 's|PATH=/root/venv_sglang211/bin:|PATH=/usr/local/cuda-13.0/bin:/root/venv_sglang211/bin:|' /etc/systemd/system/sglang-k26-eagle3.service
The PATH is also updated to include /usr/local/cuda-13.0/bin before the virtual environment's bin directory. This ensures that when FlashInfer runs which nvcc or when any subprocess invokes the CUDA compiler, it finds the 13.0 version first rather than the system's default 12.8.
Step 3: Cache Cleanup
rm -rf /root/.cache/tvm-ffi/ /root/.cache/flashinfer/ /tmp/flashinfer* 2>/dev/null
This is a crucial step. FlashInfer caches compiled JIT kernels in ~/.cache/flashinfer/, and SGLang's TVM-based JIT uses ~/.cache/tvm-ffi/. If stale binaries compiled with CUDA 12.8 headers remain in these caches, they could cause subtle runtime issues or mask the fact that the version mismatch has been fixed. Clearing the caches forces a clean rebuild with the new CUDA 13.0 toolchain.
Step 4: Systemd Reload and Verification
systemctl daemon-reload
echo 'Ready to start'
grep -E 'CUDA_HOME|PATH=' /etc/systemd/system/sglang-k26.service
After modifying the service files, systemctl daemon-reload is required to inform systemd of the changes. The assistant then verifies the configuration by grepping for the critical environment variables in the service file, confirming that CUDA_HOME points to /usr/local/cuda-13.0 and that PATH includes the CUDA 13.0 binary directory.
The Thinking Process
The assistant's reasoning throughout this debugging session demonstrates a systematic approach to infrastructure troubleshooting. The key insight was recognizing that FlashInfer's version detection and its JIT compilation are separate concerns that both depend on the CUDA toolkit. The initial workaround (setting CUDA_HOME to a nonexistent path) attempted to separate these concerns by making version detection fail while hoping compilation would still work — but both paths ultimately need nvcc.
The decision to install CUDA 13.0 via apt-get rather than downloading a runfile or using pip packages was pragmatic. The system already had CUDA repository configuration with version 13.0 packages available, as evidenced by the installed cuda-toolkit-config-common package listing version 13.2.75-1. The cuda-nvcc-13-0 package installed cleanly and brought in dependencies like libnvptxcompiler-13-0, libnvvm-13-0, and cuda-cudart-13-0 automatically.
Assumptions and Input Knowledge
To understand this message, the reader needs knowledge of several domains. First, the CUDA toolkit ecosystem: that nvcc is the CUDA compiler, that multiple toolkit versions can coexist on a system at /usr/local/cuda-X.Y, and that the CUDA_HOME environment variable controls which toolkit is used. Second, the FlashInfer JIT architecture: that it performs automatic SM capability detection, that it checks CUDA version against architecture requirements, and that it caches compiled kernels. Third, systemd service management: how Environment= directives work, how sed can modify service files, and the need for daemon-reload after changes.
The assistant assumed that installing CUDA 13.0 nvcc alongside the existing CUDA 12.8 would not cause conflicts. This assumption proved correct — the system's update-alternatives mechanism manages the /usr/local/cuda symlink, and explicitly setting CUDA_HOME in the service files ensures the correct toolkit is selected regardless of the system default.
Output Knowledge Created
This message creates several important outputs. First, it establishes a working configuration for FlashInfer on Blackwell GPUs: CUDA_HOME=/usr/local/cuda-13.0 with CUDA 13.0 nvcc. Second, it documents the exact service file modifications needed for both the autoregressive and EAGLE-3 deployments. Third, it validates that the cuda-nvcc-13-0 apt package installs cleanly and produces a functional compiler. The JIT cache cleanup ensures that subsequent service starts will trigger fresh compilation with the correct toolkit.
Conclusion
Message 11443 represents the successful resolution of a nuanced infrastructure problem that required tracing through multiple layers of software — from FlashInfer's architecture detection logic, through systemd service configuration, to CUDA toolkit installation. The fix is surgical: rather than patching FlashInfer's source code or disabling SM120 support, the assistant correctly identified that providing a compatible CUDA toolkit version was the proper solution. This approach preserves the integrity of all software components while satisfying the version requirement that FlashInfer enforces. The message stands as a model of systematic debugging: understand the error, trace the root cause, attempt a minimal fix, learn from its failure, and implement the correct solution with proper verification.