# How Claude-Video Handles yt-dlp Download Failures: Error Handling Mechanisms Explained

> Discover how Claude-Video effectively manages yt-dlp download failures. Learn about binary validation, tolerant flags, and video file verification for robust error handling.

- Repository: [bradautomates/claude-video](https://github.com/bradautomates/claude-video)
- Tags: explanation
- Published: 2026-07-10

---

**Claude-Video handles yt-dlp download failures by validating binary presence before execution, running the downloader with tolerant flags to ignore non-critical errors, and strictly verifying that a video file actually exists in the output directory before proceeding.**

Claude-Video, an open-source video processing pipeline in the `bradautomates/claude-video` repository, delegates video acquisition to **yt-dlp**. To ensure robust operation against network instability and partial failures, the wrapper implemented in [`skills/watch/scripts/download.py`](https://github.com/bradautomates/claude-video/blob/main/skills/watch/scripts/download.py) employs a multi-layered defense strategy that fails fast on missing dependencies, tolerates recoverable subtitle errors, and validates actual file output rather than relying solely on process exit codes.

## Pre-Flight Binary Validation

Before any network operation begins, the script performs a strict availability check. In [`skills/watch/scripts/download.py`](https://github.com/bradautomates/claude-video/blob/main/skills/watch/scripts/download.py), the code uses `shutil.which("yt-dlp")` to verify the binary exists in the system PATH.

If the binary is missing, the wrapper immediately raises a `SystemExit` with a descriptive message guiding the user to install the dependency. This prevents cryptic subprocess errors later in the execution.

```python

# Conceptual implementation from the source

import shutil

def _ensure_yt_dlp():
    if not shutil.which("yt-dlp"):
        raise SystemExit(
            "yt-dlp is not installed. Install with: brew install yt-dlp"
        )

```

## Tolerant Execution Flags

When invoking yt-dlp, the wrapper configures the subprocess to be resilient against non-fatal errors. Both the `download_url()` and `fetch_captions()` functions in [`skills/watch/scripts/download.py`](https://github.com/bradautomates/claude-video/blob/main/skills/watch/scripts/download.py) pass the `--ignore-errors` and `--no-playlist` flags to the yt-dlp command.

- **`--ignore-errors`**: Instructs yt-dlp to continue processing even if secondary operations (such as downloading a specific subtitle variant) encounter issues.
- **`--no-playlist`**: Prevents the downloader from attempting to fetch an entire playlist when a single video URL is provided.

This configuration ensures that partial failures—such as unavailable subtitle tracks—do not abort the primary video download.

## Post-Run Output Validation

Rather than trusting the subprocess exit code alone, Claude-Video implements strict post-run validation. After yt-dlp completes, the `_pick_video()` function inspects the output directory for a valid video file.

The logic follows this decision tree:

1. **Video file found**: The operation is considered successful regardless of yt-dlp's exit code. This handles cases where subtitle extraction fails with a non-zero code but the video downloaded correctly.
2. **No video file**: The wrapper raises a `SystemExit` that includes the exit code and target directory path, providing clear diagnostic information.

This validation occurs in [`skills/watch/scripts/download.py`](https://github.com/bradautomates/claude-video/blob/main/skills/watch/scripts/download.py) and guarantees that downstream stages in [`watch.py`](https://github.com/bradautomates/claude-video/blob/main/watch.py) (such as frame extraction and transcription) only receive confirmed valid file paths.

## Local File Path Fallback

When the source input is not a URL, the `download()` function bypasses yt-dlp entirely. The `resolve_local()` helper (also in [`skills/watch/scripts/download.py`](https://github.com/bradautomates/claude-video/blob/main/skills/watch/scripts/download.py)) validates and returns the local file path, eliminating all network-related failure modes for local video processing.

```python

# skills/watch/scripts/download.py

def download(source, out_dir, audio_only=False):
    if _is_local_file(source):
        return resolve_local(source)  # Bypasses yt-dlp

    return download_url(source, out_dir, audio_only)

```

## Practical Implementation Examples

The following examples demonstrate how to interact with the download wrapper while leveraging its built-in error handling.

### Downloading a YouTube Video

```python
from pathlib import Path
from skills.watch.scripts.download import download

result = download(
    source="https://youtu.be/abc123",
    out_dir=Path("/tmp/video-output"),
    audio_only=False
)

# Guaranteed to exist or the script exited

print(result["video_path"])

# May be None if subtitles unavailable

print(result["subtitle_path"])

```

### Handling Download Failures

```python
from pathlib import Path
from skills.watch.scripts.download import download_url

try:
    download_url(
        url="https://invalid.url/video",
        out_dir=Path("/tmp/bad-output")
    )
except SystemExit as e:
    # Contains explicit yt-dlp failure description

    print("Download failed:", e)

```

## Summary

- **Binary validation**: `shutil.which("yt-dlp")` ensures the dependency exists before any network operations commence.
- **Tolerant flags**: `--ignore-errors` and `--no-playlist` allow yt-dlp to skip over non-critical failures while preserving the main download.
- **File existence checks**: `_pick_video()` validates actual output rather than relying on exit codes, preventing partial failure states from propagating.
- **Local bypass**: `resolve_local()` handles file paths without invoking yt-dlp, eliminating network failure modes for local content.
- **Clear termination**: All fatal errors raise `SystemExit` with actionable messages, ensuring the pipeline fails fast and visibly.

## Frequently Asked Questions

### What happens if yt-dlp is not installed on the system?

The script checks for the binary using `shutil.which("yt-dlp")` in [`skills/watch/scripts/download.py`](https://github.com/bradautomates/claude-video/blob/main/skills/watch/scripts/download.py) before executing any download commands. If the binary is missing, it raises a `SystemExit` with a clear installation message, preventing ambiguous subprocess errors.

### How does Claude-Video handle partial downloads or subtitle extraction failures?

The wrapper passes `--ignore-errors` to yt-dlp, allowing it to continue even if secondary operations fail. After execution, the code validates that a video file exists in the output directory using `_pick_video()`. If the video is present, the operation succeeds regardless of subtitle extraction errors. Only the absence of a video file triggers a fatal error.

### Can I use Claude-Video with local video files instead of URLs?

Yes. When the `download()` function detects a local file path (via `resolve_local()`), it completely bypasses yt-dlp and returns the resolved path directly. This avoids all network-related failure handling and allows immediate processing of local content.

### Why does the error handler check for file existence instead of just the exit code?

Exit codes can be misleading when yt-dlp encounters non-fatal errors (such as unavailable subtitles) that return non-zero values despite successfully downloading the video. By inspecting the output directory with `_pick_video()`, Claude-Video ensures that downstream components in [`watch.py`](https://github.com/bradautomates/claude-video/blob/main/watch.py) and [`frames.py`](https://github.com/bradautomates/claude-video/blob/main/frames.py) only receive confirmed valid video files, preventing undefined state from entering the transcription pipeline.