benfred/py-spy · error

failed to get subprocesses

Error message

failed to get subprocesses

What it means

In Sampler::new_subprocess_sampler, a background thread periodically calls process.child_processes() to discover new child interpreters while recording with --subprocesses. A failed enumeration panics on that thread with "failed to get subprocesses", aborting the sampling session.

Source

Thrown at src/sampler.rs:155

                    "No python processes found in process {} or any of its subprocesses",
                    pid
                ));
            }
            std::thread::sleep(std::time::Duration::from_millis(100));
        }

        // Create a new thread to periodically monitor for new child processes, and update
        // the procesess map
        let spies = Arc::new(Mutex::new(spies));
        let monitor_spies = spies.clone();
        let monitor_config = config.clone();
        std::thread::spawn(move || {
            while process.exe().is_ok() {
                match monitor_spies.lock() {
                    Ok(mut spies) => {
                        for (childpid, parentpid) in process
                            .child_processes()
                            .expect("failed to get subprocesses")
                        {
                            if spies.contains_key(&childpid) {
                                continue;
                            }
                            match PythonSpyThread::new(childpid, Some(parentpid), &monitor_config) {
                                Ok(spy) => {
                                    spies.insert(childpid, spy);
                                }
                                Err(e) => {
                                    warn!("Failed to create spy for {}: {}", childpid, e);
                                }
                            }
                        }
                    }
                    Err(e) => {
                        error!("Failed to acquire lock: {}", e);
                    }
                }

View on GitHub (pinned to 32080cc0c2)

Solutions

  1. Keep the parent process alive for the whole recording window (record the actual server, not a shell wrapper that spawns it).
  2. Run py-spy with sudo/Administrator for the entire recording so child process metadata stays readable.
  3. Retry the recording; transient target exit mid-session is the most common cause.
  4. Record a specific child pid without --subprocesses if the tree churns constantly.

Example fix

// before: recording a shell wrapper that exits when children die
py-spy record --subprocesses -o p.svg -- ./run_workers.sh
// after: record the long-lived parent directly
WORKER_PID=$(pgrep -f worker.py | head -1)
sudo py-spy record --subprocesses -o p.svg --pid $WORKER_PID --duration 60
Defensive patterns

Strategy: retry

Validate before calling

# ensure parent stays alive and we can read its children
kill -0 "$PID" 2>/dev/null || { echo "target exited" >&2; exit 1; }
ls /proc/$PID/task >/dev/null 2>&1 || { echo 'no permission on /proc target'; exit 1; }

Try / catch

for i in 1 2 3; do
  sudo py-spy record --pid "$PID" --subprocesses -o p.svg --duration 60 && break
  pgrep -f worker.py >/dev/null || break   # don't retry if target tree is gone
  sleep 2
done

Prevention

When it happens

Trigger: Running `py-spy record --subprocesses` when child_processes() fails during sampling — the target or its children exited mid-record, permissions on process metadata changed, or an OS enumeration API returned an error mid-session.

Common situations: Long recordings where the parent exits after children finish (common with shell wrappers), jobs that kill/restart worker processes, or recordings started as root that lose privileges or vice versa.

Related errors


AI-assisted analysis of benfred/py-spy@32080cc0c2 (2026-09-05). Data as JSON: /api/errors/4c52f2cdf2fea952. Report an issue: GitHub.