Bash error: "fork: retry: Resource temporarily unavailable"

Fix "fork: retry: Resource temporarily unavailable" in Bash — usually a process ulimit or PID limit. How to diagnose it and raise the limits safely.

Error String

bash: fork: retry: Resource temporarily unavailable

Tldr

This means the kernel refused to create a new process (fork) because a limit was hit — most often the per-user process/thread ulimit (`ulimit -u`), the system-wide PID max, or available memory being exhausted. Check `ulimit -u`, `ps -u $USER | wc -l`, and system memory, then raise the limit or reduce concurrent processes.

Cause

Every command Bash runs, plus every subshell, pipeline stage, and background job, requires a fork(). If the calling user has already reached their max-processes ulimit (RLIMIT_NPROC), or the kernel is low on memory, or /proc/sys/kernel/pid_max is exhausted system-wide, fork() fails with EAGAIN, which Bash reports as this message. Runaway loops that spawn processes without limits (fork bombs, unbounded parallel xargs/GNU parallel jobs) are the classic trigger.

Repro

#!/usr/bin/env bash
for i in $(seq 1 100000); do
  sleep 60 &   # spawns unbounded background processes
done
# eventually: bash: fork: retry: Resource temporarily unavailable

Fix

#!/usr/bin/env bash
set -euo pipefail

# Check your current process limit and usage
ulimit -u
ps -u "$USER" | wc -l

# Raise the soft limit for this session (needs permission via limits.conf for a permanent change)
ulimit -u 4096

# Better: bound concurrency instead of raising limits
seq 1 100000 | xargs -P 8 -I{} sleep 1

# Check overall memory pressure too
free -h

Explanation

Fixing the immediate symptom by raising ulimit -u only postpones the problem if the root cause is an unbounded loop spawning processes. Prefer bounding concurrency with `xargs -P N` or GNU parallel `-j N`, and reserve raising RLIMIT_NPROC in /etc/security/limits.conf for services that legitimately need many processes/threads.

Faq

Q

Is this the same error as running out of memory?

A

They can look similar since both prevent fork(), but memory exhaustion shows up in `free -h` and dmesg OOM-killer logs, while a process limit shows up in `ulimit -u` vs. `ps -u $USER | wc -l`. Check both.

Q

Why does killing background jobs not immediately fix it?

A

Zombie or still-terminating processes can briefly hold slots even after you kill them. Wait a moment and recheck with `ps -u $USER | wc -l`, or use `wait` in scripts to reap children properly.

Q

How do I make a ulimit change permanent?

A

Session-scoped `ulimit -u N` only lasts for that shell. For a lasting change, add entries to /etc/security/limits.conf (e.g. "username soft nproc 4096") and ensure pam_limits is enabled.