podman-container-tools/podman · error

fork: %m

Error message

fork: %m

What it means

exec_binary() — used to run pre-exec hook binaries during podman's rootless re-exec — failed at fork() before it could exec the hook; %m is strerror(errno), almost always EAGAIN (RLIMIT_NPROC / cgroup pids.max / systemd TasksMax exhausted) or ENOMEM. Pre-exec hooks run only when /etc/containers/podman_preexec_hooks.txt exists, from LIBEXECPODMAN/pre-exec-hooks, ETC_PREEXEC_HOOKS, or $PODMAN_PREEXEC_HOOKS_DIR. The whole podman invocation exits with EXIT_FAILURE.

Source

Thrown at pkg/rootless/rootless_linux.c:375

  ret = save_ns_handles (ns_handles_path, &handles);
  saved_errno = errno;
  close (lock_fd);
  lock_fd = -1;  /* Prevent cleanup from running.  */
  errno = saved_errno;
  return ret;
}

/* exec the specified executable and exit if it fails.  */
static void
exec_binary (const char *path, char **argv, int argc)
{
  int r, status = 0;
  pid_t pid;

  pid = fork ();
  if (pid < 0)
    {
      fprintf (stderr, "fork: %m\n");
      exit (EXIT_FAILURE);
    }
  if (pid == 0)
    {
      size_t i;
      char **newargv = malloc ((argc + 2) * sizeof(char *));
      if (!newargv)
        {
          fprintf (stderr, "malloc: %m\n");
          exit (EXIT_FAILURE);
        }
      newargv[0] = (char*) path;
      for (i = 0; i < argc; i++)
        newargv[i+1] = argv[i];

      newargv[i+1] = NULL;
      errno = 0;
      execv (path, newargv);

View on GitHub (pinned to a2409076ef)

Solutions

  1. Raise the limits for the rootless user: ulimit -u, systemd TasksMax (user slice), or the session pids.max
  2. Kill leaked processes/zombies of that user to free slots, then retry the podman command
  3. If hooks are not needed, remove /etc/containers/podman_preexec_hooks.txt or the hooks directories to skip the fork entirely
  4. Verify current usage: ps -u USER -L | wc -l vs cat /sys/fs/cgroup/.../pids.max

Example fix

# before: user slice tasks exhausted
systemctl status user-1000.slice   # Tasks: 4911/4915

# after
sudo systemctl set-property user-1000.slice TasksMax=infinity
podman ps
Defensive patterns

Strategy: retry

Validate before calling

# EAGAIN at fork is the norm — verify process headroom before invoking podman
#!/bin/sh
uid=$(id -u)
slice="/sys/fs/cgroup/user.slice/user-${uid}.slice"
max=$(cat "$slice/pids.max" 2>/dev/null || echo max)
[ "$max" = max ] || {
  cur=$(cat "$slice/pids.current" 2>/dev/null || echo 0)
  [ "$cur" -lt $((max - 10)) ] || { echo "user slice pids nearly full: $cur/$max" >&2; exit 1; }
}
exec podman "$@"

Try / catch

#!/bin/sh
i=0
while ! podman "$@" 2>err.log; do
  grep -q 'fork: Resource temporarily unavailable\|fork: EAGAIN' err.log || { cat err.log >&2; exit 1; }
  i=$((i+1)); [ $i -le 3 ] || { cat err.log >&2; exit 1; }
  sleep 2
done

Prevention

When it happens

Trigger: Rootless podman re-exec with pre-exec hooks configured (indicator file /etc/containers/podman_preexec_hooks.txt present) while the user's process/thread budget is exhausted: ulimit -u hit, systemd user slice TasksMax reached, or cgroup pids.max full — fork() returns EAGAIN and podman aborts.

Common situations: Leaky workloads spawning threads until TasksMax; monitoring agents looping podman as a rootless user near nproc limits; systems where pids cgroup of the user session is shared and saturated; heavier-than-expected hook directories multiplying processes.

Related errors


AI-assisted analysis of podman-container-tools/podman@a2409076ef (2026-08-15). Data as JSON: /api/errors/c971abc5a71092e9. Report an issue: GitHub.