CUDA works on Windows but not inside WSL2
nvidia-smi works in PowerShell, fails in Ubuntu
Written by Jakub Rusinowski
The error
NVIDIA-SMI has failed because it couldn't communicate with the NVIDIA driver. Make sure that the latest NVIDIA driver is installed and running. /sbin/ldconfig.real: /usr/lib/wsl/lib/libcuda.so.1 is not a symbolic link >>> torch.cuda.is_available() False
| If you see | The cause is | Go to |
|---|---|---|
You ran apt install nvidia-driver-* or a .run installer inside WSL | The Linux driver overwrote the libcuda stub the Windows driver projects into WSL | Fix 1: remove the Linux driver from the distro |
nvidia-smi is "command not found" inside WSL | The projected driver directory is not on your PATH | Fix 2: call it at /usr/lib/wsl/lib/nvidia-smi |
| It worked, then stopped after a Windows update or sleep | The WSL VM is holding a stale projection of the host driver | Fix 3: wsl --shutdown and relaunch |
The ldconfig.real ... is not a symbolic link warning on every apt run | The read-only WSL projection cannot hold real symlinks; most loaders ignore it, some do not | Fix 5: rebuild the symlinks in a writable directory |
wsl cat /proc/version shows a kernel older than 5.10.16.3 | The WSL kernel predates usable GPU paravirtualisation | Fix 4: wsl.exe --update |
When you see it
The card is fine and Windows can see it. nvidia-smi in PowerShell prints a normal table, games run, and torch.cuda.is_available() is True in a Windows Python. Cross into your Ubuntu distro and the same GPU has vanished.
- You installed CUDA inside WSL by following a native-Linux tutorial, which told you to install the driver first.
- You picked the
cuda,cuda-13-0orcuda-driversmeta-package from the apt repo. - You are using Docker Desktop with the WSL2 backend and
--gpus allfails inside containers. - Everything worked until a Windows feature update or a long sleep, and now it does not.
- You are on Windows 10 with an older build, or on a Maxwell-generation card.
What's actually going on
WSL2 does not have its own GPU driver and is not supposed to. The NVIDIA driver you install on Windows is projected into the Linux VM at /usr/lib/wsl/lib, where it appears as libcuda.so and friends — a stub backed by the host driver. NVIDIA's guidance on this is unusually blunt: the Windows driver is the only driver you need, and you must not install any NVIDIA GPU Linux driver inside WSL 2. Installing one overwrites that projected stub with a Linux driver that has no hardware to talk to, and GPU access stays broken until you remove it. This is the cause of the overwhelming majority of "CUDA works on Windows, not in WSL" reports, and it is why the fix is subtractive rather than additive.
How to fix it
- 1
Remove any NVIDIA Linux driver you installed inside the distro
Do this first, before installing anything else. If
dpkg -l | grep nvidialists driver packages —nvidia-driver-*,libnvidia-*,nvidia-dkms-*— inside WSL, they are the problem. Purging them lets the host projection take over again on the next restart. A.runinstaller needs its own uninstaller (sudo /usr/bin/nvidia-uninstall) instead.Careful: This removes packages from the WSL distro only. It does not touch your Windows driver, your GPU, or anything outside WSL — but read the list apt prints before you confirm it.# bash, inside WSL — see what is installed dpkg -l | grep -i nvidia # Purge Linux driver packages (NOT the CUDA toolkit) sudo apt-get purge -y "nvidia-driver-*" "libnvidia-*" "nvidia-dkms-*" sudo apt-get autoremove -yDid it work?Runwsl --shutdownin PowerShell, reopen the distro, and check the projection is intact. The library should be present under/usr/lib/wsl/lib.ls -l /usr/lib/wsl/lib/libcuda.so* /usr/lib/wsl/lib/nvidia-smi - 2
Install only the WSL-Ubuntu CUDA toolkit variant
The CUDA toolkit and the display driver are separate things, and inside WSL you want the toolkit without the driver. NVIDIA publishes a WSL-Ubuntu package variant that deliberately excludes it. Choose that one from the CUDA downloads page, and do not select the
cuda,cuda-13-xorcuda-driversmeta-packages — those pull the Linux driver back in and put you straight back where you started. Ifnvidia-smiis not on your PATH after this, it lives at/usr/lib/wsl/lib/nvidia-smi.# bash, inside WSL — install the toolkit ONLY, never the driver meta-packages sudo apt-get install -y cuda-toolkit-13-0 # NOT these: # sudo apt-get install cuda # sudo apt-get install cuda-driversDid it work?The compiler reports a version and the runtime sees the device. Ifnvccworks butnvidia-smidoes not, you still have a driver problem, not a toolkit problem.nvcc --version /usr/lib/wsl/lib/nvidia-smi python3 -c "import torch; print(torch.cuda.is_available())" - 3
Restart the whole WSL VM before you debug anything else
wsl --shutdownis the cheapest fix on this page and it resolves a real class of failure: the WSL VM holds its projection of the host driver from when it started, so a Windows driver update installed under a running distro leaves the VM with a stale one. Closing the terminal window does not do this — the VM keeps running in the background for several seconds after and often longer.# PowerShell, on the Windows side wsl --shutdown wsl --status # then reopen your distroDid it work?Inside the freshly started distro,nvidia-smishould print the same GPU and driver version you see in PowerShell.nvidia-smi --query-gpu=name,driver_version --format=csv - 4
Check the platform floor — Windows build, WSL kernel, and GPU generation
GPU passthrough needs Windows 11 or Windows 10 build 19043 or newer, and a WSL kernel of at least 4.19.121 — 5.10.16.3 or newer is what you actually want. Maxwell-generation cards are not supported under WSL, and Pascal or newer is the practical requirement, which is a stricter bar than native Windows.
wsl.exe --updatepulls the current kernel.# PowerShell winver # Windows version and build wsl.exe --update wsl cat /proc/version # the WSL kernel version - 5
Fix the libcuda symlink warning without editing the read-only projection
/usr/lib/wsl/libis a read-only projection of the Windows driver, so theis not a symbolic linkwarning cannot be fixed in place — and trying is how people break a working setup. The safe form is to copy the libraries somewhere writable, recreate the symlinks there, and put that directory ahead of the WSL path in the loader config. Note that this is cosmetic for most workloads: the warning is harmless unless a loader you use actually follows the symlink.Careful: Awsl --shutdownresets the projection at/usr/lib/wsl/lib, not your copy — so after a Windows driver update your copied libraries are stale and must be recreated, or you will be running against an old libcuda.# bash, inside WSL sudo mkdir -p /usr/lib/wsl/drivers-copy sudo cp /usr/lib/wsl/lib/libcuda.so.1.1 /usr/lib/wsl/drivers-copy/ sudo ln -sf /usr/lib/wsl/drivers-copy/libcuda.so.1.1 /usr/lib/wsl/drivers-copy/libcuda.so.1 sudo ln -sf /usr/lib/wsl/drivers-copy/libcuda.so.1 /usr/lib/wsl/drivers-copy/libcuda.so echo "/usr/lib/wsl/drivers-copy" | sudo tee /etc/ld.so.conf.d/000-wsl-cuda.conf sudo ldconfigDid it work?The warning should be gone from the nextsudo ldconfigrun, and the loader should resolve libcuda to your copy.sudo ldconfig 2>&1 | grep -i libcuda || echo "no libcuda warnings" ldconfig -p | grep libcuda - 6
Consider whether you need WSL at allMost common fix
Worth saying plainly, because a lot of guides imply otherwise: for a single-GPU machine running Ollama or LM Studio, native Windows is simpler and about as fast. WSL earns its keep when you need a Linux toolchain — vLLM, a CUDA build, a Python stack that fights you on Windows. It costs you Unified Memory, which is not available under WSL, and pinned system memory, which is limited there. If you came to WSL only because a tutorial used bash, running natively removes this entire page from your life. Size the model to your card and you are done.
Check what fits your hardwarecheck which models fit your card before you spend an evening on driver plumbingOpen the VRAM checker →
If none of this worked
If nvidia-smi works inside WSL and your workload still cannot see the GPU, the problem has moved downstream to the container runtime or the framework. Docker Desktop with the WSL2 backend rides on exactly this plumbing, so fixing WSL fixes Docker — but the container also needs the NVIDIA Container Toolkit.
- Your Docker container can't see the GPU
- Ollama runs on the CPU on Windows despite an NVIDIA GPU
- "No CUDA-capable device is detected"
- Output of
wsl cat /proc/versionandwinver dpkg -l | grep -i nvidiafrom inside the distronvidia-smioutput from PowerShell and the exact failure from inside WSL- Whether you installed CUDA with the WSL-Ubuntu variant or a generic Linux package
Related
Frequently asked questions
Do I need to install an NVIDIA driver inside WSL?
No, and doing so breaks GPU access. NVIDIA states the Windows display driver is the only driver required, and that no Linux GPU driver should be installed inside WSL 2. The Windows driver is projected into the distro at /usr/lib/wsl/lib as a libcuda stub.
Why is nvidia-smi missing inside WSL when the GPU works?
It is present but not always on your PATH. It ships as part of the projected driver at /usr/lib/wsl/lib/nvidia-smi. Call it by full path to confirm the GPU is visible, then add that directory to PATH if you want the bare command to work.
Is the "libcuda.so.1 is not a symbolic link" warning serious?
Usually not. It comes from ldconfig objecting to the read-only WSL projection and most workloads run fine alongside it. It matters only when a loader you depend on follows the link. The fix is to recreate the symlinks in a writable directory, never to edit the projection.
Does WSL2 support every GPU that Windows does?
No. Maxwell-generation cards are not supported under WSL, so Pascal or newer is the practical floor — stricter than native Windows, where Ollama supports compute capability 5.0 and above. Unified Memory is also unavailable under WSL and pinned system memory is limited.
Should I run Ollama in WSL or natively on Windows?
Natively, for most single-GPU setups: it is simpler, roughly as fast, and avoids this whole class of problem. Choose WSL when you need a Linux toolchain that Windows makes painful — a CUDA build, vLLM, or a Python stack that only ships Linux wheels.