How to Troubleshoot Download Errors in ReClip: A Complete Diagnostic Guide

ReClip delegates video downloads to yt-dlp through a Flask backend with a 5-minute timeout, storing granular error details in the job status endpoint that you can inspect to diagnose specific failures.

The open-source ReClip repository (averygan/reclip) provides a web interface for downloading videos and audio using yt-dlp. Understanding how to troubleshoot download errors requires familiarity with its three-stage architecture: request handling in /api/download, background execution via run_download in app.py, and status polling through /api/status/<job_id>. When failures occur, ReClip captures stderr output, timeout conditions, and file system states to help you pinpoint whether the issue stems from yt-dlp configuration, network constraints, or environment permissions.

Understanding the Download Architecture

ReClip processes downloads through a job queue system implemented in app.py. When you submit a URL to /api/download, the backend spawns a daemon thread that executes run_download with your specified format parameters.

The run_download function (lines 36-89 in app.py) constructs the yt-dlp command based on your selection between audio extraction (-x --audio-format mp3) or video download with specific format IDs. It executes this command via subprocess.run with a hardcoded 300-second timeout (5 minutes) and captures both stdout and stderr. Upon completion, it either locates the generated file in the downloads/ directory and sets job["status"] = "done", or captures the error output and sets job["status"] = "error" along with the specific failure message.

Common Download Error Patterns and Code Paths

yt-dlp Command Execution Failures

When yt-dlp returns a non-zero exit code, run_download captures the final line of stderr and stores it in job["error"] (lines 49-52 in app.py). This typically indicates unsupported URLs, geo-blocking, or missing cookies for authenticated content.

Diagnostic signature: Check the job status endpoint and look for error messages containing yt-dlp-specific output like "ERROR:" or "Unsupported URL".

Timeout Expiration (5-Minute Limit)

Large files or slow network connections trigger subprocess.TimeoutExpired, which run_download catches at lines 84-86 in app.py. The system sets job["error"] to "Download timed out (5 min limit)" and terminates the subprocess.

Verification: Inspect your job status JSON for the exact timeout message. If the target video exceeds 1GB or your bandwidth is constrained, this is the likely culprit.

Missing Output Files After Success

Even when yt-dlp exits successfully, run_download uses glob.glob (lines 54-58 in app.py) to locate files matching downloads/{job_id}.*. If this returns an empty list—often due to permission issues or incorrect output templates—the job status indicates completion but /api/file/<job_id> returns no content.

Check: Verify the downloads/ directory exists, is writable by the Flask process, and that yt-dlp actually wrote files with the expected {job_id} prefix.

Binary Permission and Path Issues

If yt-dlp or ffmpeg are absent from the system $PATH, the subprocess fails immediately before network operations begin. Unlike yt-dlp content errors, these manifest as file-not-found or permission-denied errors in the job error field.

Fix: Confirm binary availability by running yt-dlp --version and ffmpeg -version in the same environment (Docker container or host) where app.py executes.

Step-by-Step Troubleshooting Workflow

Follow this diagnostic sequence to resolve download failures systematically:

  1. Inspect the job error payload Query the status endpoint to retrieve the exact error message stored during execution:

    curl -s http://localhost:8899/api/status/<job_id> | jq .

    Examine the "error" key for the specific yt-dlp output or timeout notification.

  2. Reproduce the yt-dlp command locally ReClip builds commands dynamically in run_download (lines 36-44 in app.py). Reconstruct and run this command manually to isolate environment issues:

    yt-dlp --no-playlist -x --audio-format mp3 \
      -o "downloads/<job_id>.%(ext)s" "<YOUR_URL>"
  3. Verify the download directory Ensure the downloads/ folder exists and permits write access:

    ls -l downloads/
    touch downloads/test_write && rm downloads/test_write
  4. Adjust the subprocess timeout For large files, modify the timeout parameter in app.py at line 48:

    result = subprocess.run(
        cmd,
        capture_output=True,
        text=True,
        timeout=1800  # 30 minutes instead of 300
    
    )
  5. Validate Docker volume mounts If running containerized, confirm the downloads/ directory is mounted as a persistent volume in your docker run command or docker-compose.yml, preventing data loss when containers restart.

Practical Debugging Examples

Polling Job Status with Error Handling

Use this JavaScript pattern to gracefully handle download failures in the frontend:

async function pollStatus(jobId) {
  const resp = await fetch(`/api/status/${jobId}`);
  const data = await resp.json();

  if (data.status === 'error') {
    console.error(`Download failed: ${data.error}`);
    alert(`Download error: ${data.error}`);
  } else if (data.status === 'done') {
    window.location.href = `/api/file/${jobId}`;
  } else {
    setTimeout(() => pollStatus(jobId), 2000);
  }
}

Manual yt-dlp Testing for Format Selection

When specific format IDs fail, test them directly outside ReClip:

JOB_ID="debug_$(date +%s)"
URL="https://www.youtube.com/watch?v=example"

# Test audio extraction

yt-dlp --no-playlist -x --audio-format mp3 \
  -o "downloads/${JOB_ID}.%(ext)s" "$URL"

# Or test specific video format

yt-dlp --no-playlist -f "137+140" \
  -o "downloads/${JOB_ID}.%(ext)s" "$URL"

Extending Timeout in the Flask Backend

For deployments handling 4K or long-form content, edit app.py to increase the timeout threshold:


# In app.py, run_download function

try:
    result = subprocess.run(
        cmd,
        capture_output=True,
        text=True,
        timeout=1800  # 30 minutes for large files

    )
except subprocess.TimeoutExpired:
    job["status"] = "error"
    job["error"] = "Download timed out (30 min limit)"
    return

Summary

  • ReClip uses yt-dlp executed through Python's subprocess module in app.py, with a default 300-second timeout that commonly triggers on large files or slow connections.
  • Error messages are granular—check /api/status/<job_id> to see whether the failure stems from yt-dlp stderr, timeout expiration, or missing output files in the downloads/ directory.
  • Local reproduction is key—reconstruct the exact command from run_download (lines 36-44) and execute it manually to bypass Flask-specific issues.
  • Binary dependencies matter—ensure both yt-dlp and ffmpeg are installed and accessible in the $PATH of the execution environment, whether native or Dockerized.

Frequently Asked Questions

Why does my download fail immediately with a yt-dlp error?

Immediate failures typically indicate that yt-dlp cannot process the URL. According to the error handling in app.py (lines 49-52), ReClip stores the final line of yt-dlp's stderr in the job error field. Common causes include unsupported platforms, geo-restricted content, or missing authentication cookies. Run the same URL with yt-dlp locally to see the full error output.

How do I fix "Download timed out" errors in ReClip?

ReClip enforces a 5-minute (300-second) timeout on the subprocess call in run_download (app.py lines 48-50). For large videos or slow connections, increase this value by modifying the timeout parameter to 1800 (30 minutes) or higher. Alternatively, use yt-dlp's -f flag to select lower-resolution formats that download faster.

Why is the downloaded file missing even though the status shows "done"?

This occurs when glob.glob in app.py (lines 54-58) cannot locate files matching downloads/{job_id}.* after yt-dlp exits successfully. Verify that the Flask process has write permissions to the downloads/ directory and that the directory exists before starting the server. In Docker deployments, ensure the volume mount persists between the download completion and file retrieval request.

Can I run ReClip without Docker to debug yt-dlp issues?

Yes, running the Flask backend directly simplifies debugging. Install dependencies from requirements.txt, ensure yt-dlp and ffmpeg are in your system PATH, then execute python app.py. This allows you to add print(cmd) statements in run_download to see the exact command being executed and observe real-time yt-dlp output without container abstraction layers.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →