A TensorFlow GPU failure often appears as a clean import followed by an empty device list from tf.config.list_physical_devices('GPU'). That symptom means Python is running TensorFlow, but the active environment has not connected TensorFlow to an NVIDIA GPU runtime.

The current pip GPU path depends on the host NVIDIA driver reporting the device, a supported Linux x86_64 or WSL2 target, and the packaged CUDA libraries installed into the active Python environment through tensorflow[and-cuda]. Fix the layer that fails first instead of reinstalling TensorFlow repeatedly.

Native Windows GPU support ended after TensorFlow 2.10, and current macOS packages do not provide the official CUDA path. On a supported Linux or WSL2 system where nvidia-smi works, the common virtual-environment repair is to refresh the GPU package, add TensorFlow's NVIDIA library symlinks, add the ptxas symlink, and retest the original empty device list.

Steps to fix TensorFlow GPU detection:

  1. Activate the Python environment where TensorFlow returns an empty GPU list.
    $ source ~/venvs/tf-gpu/bin/activate
    (tf-gpu) $

    Use the equivalent conda activate tf-gpu command for a Conda-managed environment.
    Related: How to create a virtual environment for TensorFlow
    Related: How to create a Conda environment for TensorFlow

  2. Reproduce the TensorFlow GPU detection symptom from that environment.
    (tf-gpu) $ python -c "import tensorflow as tf; print(tf.__version__); print(tf.config.list_physical_devices('GPU'))"
    2.21.0
    []

    An empty list confirms TensorFlow imported but did not expose a physical GPU to Python.
    Related: How to check the TensorFlow version

  3. Confirm that the host NVIDIA driver sees the GPU.
    (tf-gpu) $ nvidia-smi
    Mon Jun 29 04:26:18 2026
    +-----------------------------------------------------------------------------------------+
    | NVIDIA-SMI 575.64.03              Driver Version: 575.64.03      CUDA Version: 12.9     |
    |-----------------------------------------+------------------------+----------------------|
    | GPU  Name                 Persistence-M | Bus-Id          Disp.A | Volatile Uncorr. ECC |
    |  0   NVIDIA RTX 4080 SUPER         Off  | 00000000:01:00.0  Off |                  Off |
    ##### snipped #####

    If nvidia-smi fails or shows no GPU, repair the host driver or WSL2 GPU passthrough before changing Python packages. The TensorFlow package cannot replace a missing kernel driver.

  4. Confirm that the environment is running on the supported Linux GPU target.
    (tf-gpu) $ uname -m
    x86_64

    Use the current pip GPU path on Linux x86_64 or WSL2. Current native Windows and macOS packages do not expose CUDA GPUs for new TensorFlow releases.

  5. Refresh the active environment with TensorFlow's GPU package extra.
    (tf-gpu) $ python -m pip install --upgrade "tensorflow[and-cuda]"
    Requirement already satisfied: tensorflow in /home/user/venvs/tf-gpu/lib/python3.12/site-packages (2.21.0)
    Collecting nvidia-cudnn-cu12<10.0,>=9.3.0.75
    ##### snipped #####
    Successfully installed keras-3.14.0 nvidia-cudnn-cu12-9.21.0.82 tensorflow-2.21.0

    The and-cuda extra installs the NVIDIA user-space packages into the active environment. It still depends on a working host driver.
    Related: How to install TensorFlow with pip

  6. Locate the TensorFlow package directory that will receive the NVIDIA library links.
    (tf-gpu) $ python -c "import tensorflow as tf; print(tf.__file__)"
    /home/user/venvs/tf-gpu/lib/python3.12/site-packages/tensorflow/__init__.py
  7. Add the packaged NVIDIA shared libraries to the TensorFlow package directory.
    (tf-gpu) $ pushd $(dirname $(python -c 'print(__import__("tensorflow").__file__)'))
    ~/venvs/tf-gpu/lib/python3.12/site-packages/tensorflow ~/project
    (tf-gpu) $ ln -svf ../nvidia/*/lib/*.so* .
    './libcudart.so.12' -> '../nvidia/cuda_runtime/lib/libcudart.so.12'
    ##### snipped #####
    (tf-gpu) $ popd
    ~/project

    This follows TensorFlow's current virtual-environment repair for GPU tests that fail because packaged CUDA components are not discovered automatically.

  8. Add the ptxas link inside the active virtual environment.
    (tf-gpu) $ ln -sf $(find $(dirname $(dirname $(python -c "import nvidia.cuda_nvcc; print(nvidia.cuda_nvcc.__file__)"))/*/bin/) -name ptxas -print -quit) $VIRTUAL_ENV/bin/ptxas

    For Conda, replace $VIRTUAL_ENV/bin/ptxas with the active environment's bin/ptxas path when $VIRTUAL_ENV is empty.

  9. Retest the original TensorFlow GPU check.
    (tf-gpu) $ python -c "import tensorflow as tf;print(tf.config.list_physical_devices('GPU'))"
    [PhysicalDevice(name='/physical_device:GPU:0', device_type='GPU')]

    If the list remains empty after nvidia-smi works and the symlinks are in place, rebuild the environment from a supported Python interpreter and the current pip GPU package instead of mixing system CUDA paths into the environment.
    Related: How to build a TensorFlow GPU environment

  10. Run a small operation and confirm TensorFlow places it on the GPU device.
    (tf-gpu) $ python -c "import tensorflow as tf; print(tf.matmul(tf.ones((128, 128)), tf.ones((128, 128))).device)"
    /job:localhost/replica:0/task:0/device:GPU:0

    After the device path reports GPU:0, configure memory growth if the process should avoid reserving most GPU memory at startup.
    Related: How to enable TensorFlow GPU memory growth