2025, Nov 01 19:00
Troubleshooting pip Permission denied and NumPy import errors in a Python 3.12 venv on Ubuntu 24.04 (noexec mount)
Learn why pip shows Permission denied and NumPy fails to import in a Python 3.12 venv on Ubuntu 24.04: noexec mount. Fix via python -m pip or remount with exec.
When a virtual environment looks activated but pip refuses to cooperate, the culprit can be outside Python entirely. On Ubuntu 24.04 with Python 3.12, a venv created under a mount point that disallows execution can cause pip to fall back to the system copy and compiled wheels to fail at import time. The symptoms are confusing at first glance: Python from the venv runs, pip points to the global one, and attempts to execute the venv’s pip end in “Permission denied.” If you push through with python -m pip, installing NumPy seems to work—until importing it fails with a shared object mapping error.
Reproducing the issue
The workflow starts in a directory on a mount under /mnt:
python3 -m venv .venv
source ./.venv/bin/activate
which pip
which python
./.venv/bin/pip install numpy
The output shows the mismatch and the failure to execute the venv’s pip:
(.venv) $ which pip
/usr/bin/pip
(.venv) $ which python
/mnt/DATA/AUC/Research Assistant/Pedestrian-Estimation-Dataset-Annotation/test/.venv/bin/python
(.venv) $ ./.venv/bin/pip install numpy
bash: ./.venv/bin/pip: Permission denied
Installing via the interpreter works:
python -m pip install numpy
But importing a compiled extension like NumPy then fails from that environment:
ImportError: ... _multiarray_umath.cpython-312-x86_64-linux-gnu.so: failed to map segment from shared object
...
ImportError: Error importing numpy: you should not try to import numpy from
its source directory; please exit the numpy source tree, and relaunch
your python interpreter from there.
A minimal script that triggers the import phase is enough to surface the error:
# file: run_infer.py
import numpy as nx
print(nx.__version__)
What’s actually going on
The problem isn’t pip, Python, or NumPy. It’s the filesystem mount options. The environment lives on a path under /mnt that was mounted with noexec. That flag prevents executing binaries and scripts from that filesystem, regardless of file permissions. As a result, your shell won’t consider .venv/bin/pip a valid executable and shows /usr/bin/pip instead. Even if you call the venv’s pip by path, the kernel denies execution with “Permission denied.”
The same restriction also breaks loading compiled extensions, which explains the “failed to map segment from shared object” during NumPy import. In the reported setup, the device was formatted as NTFS and mounted via fuseblk with noexec. Confirming the mount options makes the picture clear:
mount | grep -F /mnt
Example output that demonstrates the issue includes noexec in the flags:
(rw,nosuid,nodev,noexec,relatime,user_id=0,group_id=0,default_permissions,allow_other,blksize=4096,user,x-gvfs-show)
How to fix it
There are two straightforward ways to proceed. The first is to operate within the current restriction by invoking pip through the interpreter so that the kernel executes python (which is allowed) and Python loads the module as a script:
python .venv/bin/pip <args>
or equivalently:
python -m pip <args>
The second is to remove the restriction at the source. If the venv (and your project) reside on a filesystem mounted with noexec, remount it with exec so that executables and shared objects can run. The fstab entry before the change looked like this:
UUID=349264BD926484E8 /mnt/DATA auto rw,user,uid=1000,gid=1000,dmask=0002,fmask=0002,nosuid,nodev,nofail,x-gvfs-show 0 0
Adding exec enables execution on that mount:
UUID=349264BD926484E8 /mnt/DATA auto rw,user,exec,uid=1000,gid=1000,dmask=0002,fmask=0002,nosuid,nodev,nofail,x-gvfs-show 0 0
After applying the change and remounting, the venv’s pip executes normally, and importing NumPy works without errors. An alternative is to recreate the virtual environment on a filesystem that is not mounted with noexec.
Why this matters
Virtual environments rely on shims and entry points under the venv’s bin directory. If the underlying filesystem forbids execution, the usual guarantees of isolation break down in subtle ways. The shell silently resolves pip to the global copy, making installations leak outside the environment. Compiled wheels load shared objects at import time; with noexec in place, the loader can’t map segments correctly, which surfaces as cryptic ImportError messages. Fixing the mount options restores expected behavior and prevents hard-to-diagnose runtime errors.
Conclusion
If pip in an activated venv resolves to the system binary or the venv’s pip fails with “Permission denied,” check mount options before debugging Python. A quick look at mount | grep -F /mnt will reveal noexec on common external or NTFS-backed mounts. Use python -m pip as a stopgap, then either remount with exec or move the environment to a filesystem without noexec. Once execution is permitted, pip and compiled extensions like NumPy behave as expected, and your virtual environment stays truly isolated.