Skip to content
Latchkey

Python "BrokenProcessPool" with concurrent.futures in CI

A worker in a ProcessPoolExecutor exited without returning a result - killed by the OOM reaper, a segfault, or an uncaught fatal signal. The executor cannot recover and marks the whole pool broken.

What this error means

A parallel step fails with "concurrent.futures.process.BrokenProcessPool: A process in the process pool was terminated abruptly while the future was running or pending." It is often intermittent under memory pressure.

python
concurrent.futures.process.BrokenProcessPool: A process in the process
pool was terminated abruptly while the future was running or pending.

Common causes

A worker was OOM-killed

Each worker holds its own copy of large data; collectively they exceed runner memory and the kernel kills one, breaking the pool.

A native crash inside a worker

A C-extension segfault or an uncaught fatal signal terminates a worker process without a Python-level exception.

How to fix it

Reduce memory pressure or worker count

  1. Lower max_workers so total memory stays within the runner.
  2. Chunk inputs so each task holds less data at once.
  3. Re-run and watch peak memory.
Python
from concurrent.futures import ProcessPoolExecutor
with ProcessPoolExecutor(max_workers=2) as ex:   # was os.cpu_count()
    results = list(ex.map(work, chunks))

Isolate the crashing task

Run the suspect task in-process to surface the real exception or segfault the pool was hiding.

Python
# run one task directly to see the underlying crash
work(chunks[0])

How to prevent it

  • Size max_workers to the runner memory, not just CPU count.
  • Chunk large inputs so per-worker memory stays bounded.
  • Guard native extension calls that can crash workers.

Related guides

Tired of flaky CI? Latchkey auto-heals failed jobs and retries them for you. Start free →