Panniantong/Agent-Reach · error · TranscribeError

{cmd[0]} failed (exit {proc.returncode}): {proc.stderr.strip

Error message

{cmd[0]} failed (exit {proc.returncode}): {proc.stderr.strip()[:300]}

What it means

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).

Source

Thrown at agent_reach/transcribe.py:172

def _run(cmd: List[str], timeout: int = 600) -> None:
    """Run a subprocess, raising TranscribeError on nonzero exit or timeout.

    cmd carries user-supplied URLs/paths into yt-dlp/ffmpeg — a stalled
    network read or a hung probe must not block the CLI forever.
    """
    try:
        proc = subprocess.run(
            cmd,
            capture_output=True,
            encoding="utf-8",
            errors="replace",
            timeout=timeout,
        )
    except subprocess.TimeoutExpired:
        raise TranscribeError(f"{cmd[0]} timed out after {timeout}s")
    if proc.returncode != 0:
        raise TranscribeError(
            f"{cmd[0]} failed (exit {proc.returncode}): {proc.stderr.strip()[:300]}"
        )


def _literal_ip(host: str):
    """Return the address a literal host denotes, or None for a real hostname.

    ``ipaddress`` only accepts the canonical dotted-quad form, but the C
    resolver behind yt-dlp accepts the whole ``inet_aton`` grammar: ``127.1``,
    ``2130706433``, ``0x7f000001`` and ``0177.0.0.1`` all reach 127.0.0.1, and
    ``0xA9FEA9FE`` reaches the cloud metadata endpoint. Parsing with the same
    grammar keeps those shorthands from slipping past the private-address
    check. This is literal parsing only — no name is resolved here.
    """
    try:
        return ipaddress.ip_address(host)
    except ValueError:
        pass

View on GitHub (pinned to 93ae1d18c3)

Solutions

  1. Read the embedded stderr text — it names the real cause; fix that first
  2. If stderr mentions extraction/NSIG/sign-in: upgrade yt-dlp (pip install -U yt-dlp) and retry
  3. Test the same command manually: yt-dlp -x --audio-format m4a -o 'source.%(ext)s' -- <url> and ffmpeg re-encode on the produced file
  4. If ffmpeg failed: confirm the input file plays (ffprobe it) and the out_dir is writable with enough disk space

Example fix

# before: failing call
text = transcribe("https://www.youtube.com/watch?v=deleted")
# yt-dlp failed (exit 1): ERROR: [youtube] deleted: Video unavailable

# after: verify extractability first, give a clear message
import subprocess
probe = subprocess.run(["yt-dlp", "--simulate", "--", url], capture_output=True, text=True)
if probe.returncode != 0:
    raise RuntimeError(f"media not fetchable: {probe.stderr.strip()[:200]}")
text = transcribe(url)
Defensive patterns

Strategy: try-catch

Validate before calling

import subprocess

def media_fetchable(url: str) -> bool:
    return subprocess.run(
        ["yt-dlp", "--simulate", "--", url],
        capture_output=True, text=True,
    ).returncode == 0

Try / catch

from agent_reach.transcribe import TranscribeError
try:
    text = transcribe(url)
except TranscribeError as e:
    if "failed (exit" in str(e):
        detail = str(e).split(":", 1)[-1]  # stderr excerpt names the real cause
        handle_media_failure(detail)
    raise

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of Panniantong/Agent-Reach@93ae1d18c3 (2026-08-14). Data as JSON: /api/errors/97d4734fc6fdf0d1. Report an issue: GitHub.