{"record":{"id":"2f82f70e84aa8d2e","repo":"nexu-io/open-design","slug":"command-cmd-0-timed-out-after-timeout-s","errorCode":null,"errorMessage":"Command {cmd[0]} timed out after {timeout}s","messagePattern":"Command (.+?) timed out after (.+?)s","errorType":"exception","errorClass":"SubprocTimeout","httpStatus":null,"severity":"error","filePath":"design-templates/last30days/scripts/lib/subproc.py","lineNumber":88,"sourceCode":"        preexec_fn=preexec,\n        env=env,\n    )\n\n    if on_pid is not None:\n        try:\n            on_pid(proc.pid)\n        except Exception:\n            pass\n\n    try:\n        stdout, stderr = proc.communicate(timeout=timeout)\n    except subprocess.TimeoutExpired:\n        try:\n            os.killpg(os.getpgid(proc.pid), signal.SIGTERM)\n        except (ProcessLookupError, PermissionError, OSError):\n            proc.kill()\n        proc.wait(timeout=5)\n        raise SubprocTimeout(f\"Command {cmd[0]} timed out after {timeout}s\")\n\n    return SubprocResult(\n        returncode=proc.returncode,\n        stdout=stdout or \"\",\n        stderr=stderr or \"\",\n    )\n","sourceCodeStart":70,"sourceCodeEnd":95,"githubUrl":"https://github.com/nexu-io/open-design/blob/5be4028344c2eb4c667c5a97bda8f750c5597ef7/design-templates/last30days/scripts/lib/subproc.py#L70-L95","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Raise the timeout argument to match the workload (depth=deep needs more headroom).","Reproduce the failing command in a shell to see where it stalls (network, auth prompt, deadlock).","Ensure the child does not expect interactive input; pass all required credentials via env/args.","Catch SubprocTimeout and degrade gracefully (skip that source) instead of aborting the whole pipeline."],"exampleFix":"# before\nres = run(['bird-scrape', query], timeout=30)  # deep transcription stalls\n\n# after\nfrom lib.subproc import SubprocTimeout\ntry:\n    res = run(['bird-scrape', query], timeout=180)\nexcept SubprocTimeout:\n    res = None  # skip this source, continue pipeline","handlingStrategy":"try-catch","validationCode":"null","typeGuard":"null","tryCatchPattern":"from lib.subproc import run, SubprocTimeout\n\ntry:\n    res = run(cmd, timeout=timeout)\nexcept SubprocTimeout:\n    res = None  # degrade: skip this source, keep the pipeline running","preventionTips":["Size the timeout to the workload (depth=deep needs more time).","Ensure external CLIs receive all input via env/args, never interactive prompts.","Reproduce the stalled command manually to find the bottleneck before raising the timeout."],"tags":["subprocess","timeout","resource","external-cli"],"backgroundTag":null,"analyzedSha":"5be4028344c2eb4c667c5a97bda8f750c5597ef7","analyzedAt":"2026-08-12T12:03:58.812Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}