nexu-io/open-design · error · SubprocTimeout

Command {cmd[0]} timed out after {timeout}s

Error message

Command {cmd[0]} timed out after {timeout}s

What it means

SubprocTimeout raised by the run helper in subproc.py when proc.communicate(timeout=timeout) raises subprocess.TimeoutExpired. The helper kills the whole process group (SIGTERM via os.killpg, or proc.kill as fallback), waits up to 5s for reaping, then re-raises as SubprocTimeout so callers can distinguish timeouts from normal exit codes.

Source

Thrown at design-templates/last30days/scripts/lib/subproc.py:88

        preexec_fn=preexec,
        env=env,
    )

    if on_pid is not None:
        try:
            on_pid(proc.pid)
        except Exception:
            pass

    try:
        stdout, stderr = proc.communicate(timeout=timeout)
    except subprocess.TimeoutExpired:
        try:
            os.killpg(os.getpgid(proc.pid), signal.SIGTERM)
        except (ProcessLookupError, PermissionError, OSError):
            proc.kill()
        proc.wait(timeout=5)
        raise SubprocTimeout(f"Command {cmd[0]} timed out after {timeout}s")

    return SubprocResult(
        returncode=proc.returncode,
        stdout=stdout or "",
        stderr=stderr or "",
    )

View on GitHub (pinned to 5be4028344)

Solutions

  1. Raise the timeout argument to match the workload (depth=deep needs more headroom).
  2. Reproduce the failing command in a shell to see where it stalls (network, auth prompt, deadlock).
  3. Ensure the child does not expect interactive input; pass all required credentials via env/args.
  4. Catch SubprocTimeout and degrade gracefully (skip that source) instead of aborting the whole pipeline.

Example fix

# before
res = run(['bird-scrape', query], timeout=30)  # deep transcription stalls

# after
from lib.subproc import SubprocTimeout
try:
    res = run(['bird-scrape', query], timeout=180)
except SubprocTimeout:
    res = None  # skip this source, continue pipeline
Defensive patterns

Strategy: try-catch

Validate before calling

null

Type guard

null

Try / catch

from lib.subproc import run, SubprocTimeout

try:
    res = run(cmd, timeout=timeout)
except SubprocTimeout:
    res = None  # degrade: skip this source, keep the pipeline running

Prevention

When it happens

Trigger: Calling run(cmd, timeout=N) where the child process does not exit within N seconds. Used by backends like bird_x.py to spawn external CLIs (e.g. the bird scraper) that hang on network/auth issues.

Common situations: External CLI blocked on a network call, an interactive prompt, or a deadlock. Timeout value too low for the workload (e.g. transcription-heavy depth=deep). Child waiting on stdin that was never closed.

Understand the failure class

Related errors


AI-assisted analysis of nexu-io/open-design@5be4028344 (2026-08-12). Data as JSON: /api/errors/2f82f70e84aa8d2e. Report an issue: GitHub.