Python 3.14 on linux sandbox multiprocessing issue
What issue are you seeing?
Running Python formatting tools from the project virtualenv under the Codex sandbox fails when the tool uses Python multiprocessing on Python 3.14.
Observed environment:
- Workspace:
/home/thedoctorjtd/codex-misc - Python executable:
/home/thedoctorjtd/codex-misc/.venv/bin/python - Python version:
3.14.5 - Platform:
Linux-5.15.0-179-generic-x86_64-with-glibc2.35 autoflake==2.3.3black==26.5.1isort==8.0.1
The failures are:
autoflakefails by default when run recursively, becauseautoflake --jobs 0creates amultiprocessing.Pool.blackfails by default when formatting multiple files, because it usesconcurrent.futures.ProcessPoolExecutor.isortdoes not fail in the default command tested here, but it fails the same way if parallel jobs are requested with--jobs -1.
The common traceback ends in Python 3.14's forkserver startup:
File "/home/thedoctorjtd/.pyenv/versions/3.14.5/lib/python3.14/multiprocessing/forkserver.py", line 167, in ensure_running
listener.bind(address)
PermissionError: [Errno 1] Operation not permitted
This appears to be a sandbox interaction with Python 3.14's default multiprocessing start method. In Python 3.14 on POSIX, the default start method is now forkserver; in this environment multiprocessing.get_start_method() returns forkserver. The forkserver path creates an AF_UNIX listener socket before worker processes are started, and socket creation/bind operations are denied inside the sandbox.
I confirmed the issue is sandbox-specific:
- The same
autoflakecommand succeeds outside the sandbox. - The same
blackcommand succeeds outside the sandbox. - A minimal
forkservermultiprocessing repro succeeds outside the sandbox. - A minimal
AF_UNIXsocket bind succeeds outside the sandbox.
What steps can reproduce the bug?
In any sandboxed workspace using a Python 3.14 virtualenv, create a test directory with multiple Python files. For example, create sandbox_py314_repro/ with several .py files containing unformatted code and unused imports.
Then run the project venv Python commands inside the sandbox:
.venv/bin/python --version
.venv/bin/python -m pip show autoflake black isort
.venv/bin/python -c 'import multiprocessing as mp; print(mp.get_start_method())'
Observed:
Python 3.14.5
autoflake 2.3.3
black 26.5.1
isort 8.0.1
forkserver
Run the requested formatter sequence:
.venv/bin/python -m autoflake --in-place --recursive --remove-all-unused-imports --remove-unused-variables sandbox_py314_repro
.venv/bin/python -m black sandbox_py314_repro
.venv/bin/python -m isort sandbox_py314_repro
.venv/bin/python -m autoflake --in-place --recursive --remove-all-unused-imports --remove-unused-variables sandbox_py314_repro
Observed results:
- First
autoflake: fails withPermissionError: [Errno 1] Operation not permittedatmultiprocessing/forkserver.py,listener.bind(address). black: fails withPermissionError: [Errno 1] Operation not permittedat the same forkserver listener bind.isort: succeeds by default.- Second
autoflake: fails the same way as the first.
A minimal reproduction without formatter dependencies:
.venv/bin/python -c 'import multiprocessing as mp; print(mp.get_context("forkserver").Pool(1).map(int, ["1"]))'
Observed sandbox result:
PermissionError: [Errno 1] Operation not permitted
The same operation using explicit fork succeeds in the sandbox:
.venv/bin/python -c 'import multiprocessing as mp; print(mp.get_context("fork").Pool(1).map(int, ["1"]))'
Observed sandbox result:
[1]
The underlying sandbox socket restriction can be reproduced directly:
.venv/bin/python -c 'import socket,tempfile,os; path=os.path.join(tempfile.mkdtemp(), "sock-test"); s=socket.socket(socket.AF_UNIX); s.bind(path); print(path)'
Observed sandbox result:
PermissionError: [Errno 1] Operation not permitted
What is the expected behavior?
Python tools that create local worker processes should be able to run in the sandbox when the worker processes only operate on allowed workspace files.
For Python 3.14 specifically, the sandbox should either allow the local AF_UNIX socket operations needed by Python's forkserver multiprocessing start method, or provide a compatibility path so normal multiprocessing.Pool and ProcessPoolExecutor usage does not fail with PermissionError.
The formatter commands should behave the same way they do outside the sandbox:
autoflake: exits 0
black: reformats or reports files unchanged, exits 0
isort: exits 0
Additional information
Python 3.14 changed the default POSIX multiprocessing start method from fork to forkserver. The Python 3.14 multiprocessing documentation notes that forkserver became the default on POSIX platforms and that fork is no longer the default on any platform: https://docs.python.org/3/library/multiprocessing.html#contexts-and-start-methods
This explains why the issue is not seen with Python 3.10 or Python 3.12 default multiprocessing behavior in the same sandbox:
python3.10 -c 'import multiprocessing as mp; print(mp.get_start_method()); print(mp.Pool(1).map(int, ["1"]))'
python3.12 -c 'import multiprocessing as mp; print(mp.get_start_method()); print(mp.Pool(1).map(int, ["1"]))'
Observed sandbox result for both:
fork
[1]
However, Python 3.12 can reproduce the same failure if forkserver is requested explicitly:
python3.12 -c 'import multiprocessing as mp; print(mp.get_context("forkserver").Pool(1).map(int, ["1"]))'
Observed sandbox result:
PermissionError: [Errno 1] Operation not permitted
Workarounds verified in the sandbox:
.venv/bin/python -m autoflake --check --recursive --jobs 1 --remove-all-unused-imports --remove-unused-variables sandbox_py314_repro
.venv/bin/python -m black --check --workers 1 sandbox_py314_repro
Both avoid the sandbox PermissionError because they avoid creating a process pool. Their exit codes still follow normal tool semantics; for example, --check can exit non-zero if files need changes. These are only workarounds; the underlying issue is that Python 3.14's default multiprocessing path now needs local socket operations that the sandbox denies.
Related observation:
.venv/bin/python -m isort --check-only --jobs -1 sandbox_py314_repro
This also fails with the same forkserver listener.bind(address) PermissionError, confirming that isort is affected when its parallel mode is used.
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗