{"record":{"id":"97d4734fc6fdf0d1","repo":"Panniantong/Agent-Reach","slug":"cmd-0-failed-exit-proc-returncode-proc-st","errorCode":null,"errorMessage":"{cmd[0]} failed (exit {proc.returncode}): {proc.stderr.strip()[:300]}","messagePattern":"(.+?) failed \\(exit (.+?)\\): (.+?)","errorType":"exception","errorClass":"TranscribeError","httpStatus":null,"severity":"error","filePath":"agent_reach/transcribe.py","lineNumber":172,"sourceCode":"\ndef _run(cmd: List[str], timeout: int = 600) -> None:\n    \"\"\"Run a subprocess, raising TranscribeError on nonzero exit or timeout.\n\n    cmd carries user-supplied URLs/paths into yt-dlp/ffmpeg — a stalled\n    network read or a hung probe must not block the CLI forever.\n    \"\"\"\n    try:\n        proc = subprocess.run(\n            cmd,\n            capture_output=True,\n            encoding=\"utf-8\",\n            errors=\"replace\",\n            timeout=timeout,\n        )\n    except subprocess.TimeoutExpired:\n        raise TranscribeError(f\"{cmd[0]} timed out after {timeout}s\")\n    if proc.returncode != 0:\n        raise TranscribeError(\n            f\"{cmd[0]} failed (exit {proc.returncode}): {proc.stderr.strip()[:300]}\"\n        )\n\n\ndef _literal_ip(host: str):\n    \"\"\"Return the address a literal host denotes, or None for a real hostname.\n\n    ``ipaddress`` only accepts the canonical dotted-quad form, but the C\n    resolver behind yt-dlp accepts the whole ``inet_aton`` grammar: ``127.1``,\n    ``2130706433``, ``0x7f000001`` and ``0177.0.0.1`` all reach 127.0.0.1, and\n    ``0xA9FEA9FE`` reaches the cloud metadata endpoint. Parsing with the same\n    grammar keeps those shorthands from slipping past the private-address\n    check. This is literal parsing only — no name is resolved here.\n    \"\"\"\n    try:\n        return ipaddress.ip_address(host)\n    except ValueError:\n        pass","sourceCodeStart":154,"sourceCodeEnd":190,"githubUrl":"https://github.com/Panniantong/Agent-Reach/blob/93ae1d18c37b707dec053c7c4f9d91cd8ef8943d/agent_reach/transcribe.py#L154-L190","documentation":"Raised by _run (transcribe.py:171-174) when yt-dlp or ffmpeg exits nonzero. The message includes the binary name, exit code, and the first 300 chars of stderr, which is usually the actionable detail (extraction failure, codec error, disk full).","triggerScenarios":"yt-dlp: deleted/private video, geoblocked content, unsupported site, SIGSEGV from a broken yt-dlp install. ffmpeg: corrupt input downloaded to out_dir, missing encoder (native aac should exist everywhere), unreadable/out-of-space output directory.","commonSituations":"Stale yt-dlp version that no longer matches a site's extractor (YouTube changes frequently — most common real-world hit), passing a URL the site requires auth for, or a leftover source.* file in a reused out_dir confusing the glob.","solutions":["Read the embedded stderr text — it names the real cause; fix that first","If stderr mentions extraction/NSIG/sign-in: upgrade yt-dlp (pip install -U yt-dlp) and retry","Test the same command manually: yt-dlp -x --audio-format m4a -o 'source.%(ext)s' -- <url> and ffmpeg re-encode on the produced file","If ffmpeg failed: confirm the input file plays (ffprobe it) and the out_dir is writable with enough disk space"],"exampleFix":"# before: failing call\ntext = transcribe(\"https://www.youtube.com/watch?v=deleted\")\n# yt-dlp failed (exit 1): ERROR: [youtube] deleted: Video unavailable\n\n# after: verify extractability first, give a clear message\nimport subprocess\nprobe = subprocess.run([\"yt-dlp\", \"--simulate\", \"--\", url], capture_output=True, text=True)\nif probe.returncode != 0:\n    raise RuntimeError(f\"media not fetchable: {probe.stderr.strip()[:200]}\")\ntext = transcribe(url)","handlingStrategy":"try-catch","validationCode":"import subprocess\n\ndef media_fetchable(url: str) -> bool:\n    return subprocess.run(\n        [\"yt-dlp\", \"--simulate\", \"--\", url],\n        capture_output=True, text=True,\n    ).returncode == 0","typeGuard":null,"tryCatchPattern":"from agent_reach.transcribe import TranscribeError\ntry:\n    text = transcribe(url)\nexcept TranscribeError as e:\n    if \"failed (exit\" in str(e):\n        detail = str(e).split(\":\", 1)[-1]  # stderr excerpt names the real cause\n        handle_media_failure(detail)\n    raise","preventionTips":["Keep yt-dlp current (pip install -U yt-dlp) — stale extractors cause most nonzero exits","Run yt-dlp --simulate before batch jobs to filter dead/geoblocked URLs","Always surface the embedded stderr text when reporting the error"],"tags":["subprocess","yt-dlp","ffmpeg","exit-code"],"backgroundTag":null,"analyzedSha":"93ae1d18c37b707dec053c7c4f9d91cd8ef8943d","analyzedAt":"2026-08-14T22:54:06.735Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}