langchain-ai/deepagents · error · VideoExtractionError

Failed to open video payload: {exc}

Error message

Failed to open video payload: {exc}

What it means

PyAV failed to open the video byte payload, and `_open_video_container` normalizes every backend open failure (OSError, av.error types) into `VideoExtractionError`. This means the bytes are not decodable as a media container by the installed PyAV/FFmpeg.

Source

Thrown at libs/deepagents/deepagents/middleware/_video.py:227

        raise ValueError(msg)
    if duration_seconds <= 0:
        msg = f"duration_seconds must be > 0, got {duration_seconds!r}"
        raise ValueError(msg)


def _open_video_container(av: Any, content: bytes) -> Any:  # noqa: ANN401  # PyAV types are unavailable without the [video] extra
    """Open a video byte payload, normalizing PyAV's failure modes.

    PyAV typically raises `av.error.InvalidDataError` for malformed inputs,
    but it falls back to `OSError` when the system ffmpeg library is missing
    or incompatible. Both surface to callers as `VideoExtractionError` so
    the middleware does not have to distinguish between them.
    """
    try:
        return av.open(io.BytesIO(content))
    except _video_backend_error_types(av) as exc:  # pragma: no cover - depends on host/input
        msg = f"Failed to open video payload: {exc}"
        raise VideoExtractionError(msg) from exc


def _video_backend_error_types(av: Any) -> tuple[type[BaseException], ...]:  # noqa: ANN401  # PyAV types are unavailable without the [video] extra
    """Return backend failures that should surface as `VideoExtractionError`."""
    errors: list[type[BaseException]] = [OSError]
    av_error = getattr(av, "error", None)
    for name in ("FFmpegError", "InvalidDataError"):
        error_type = getattr(av_error, name, None)
        if (
            isinstance(error_type, type)
            and issubclass(error_type, BaseException)
            and not any(issubclass(error_type, existing) for existing in errors)
        ):
            errors.append(error_type)
    return tuple(errors)


def _find_video_stream(container: Any) -> Any:  # noqa: ANN401  # PyAV types are unavailable without the [video] extra

View on GitHub (pinned to a1af029e6e)

Solutions

  1. Verify the bytes are a real video (check magic bytes / try ffprobe on the saved file)
  2. Re-download or re-export the video; confirm the download completed (Content-Length check)
  3. Catch `VideoExtractionError` and treat the file as unsupported, skipping it
  4. Upgrade the `deepagents[video]` extra / PyAV and FFmpeg to support newer containers

Example fix

// before
result = extract_video_frames(response.content, offset_seconds=0, duration_seconds=10, sampling_rate=1)
// after
try:
    result = extract_video_frames(response.content, offset_seconds=0, duration_seconds=10, sampling_rate=1)
except VideoExtractionError as exc:
    logger.warning("Skipping undecodable video: %s", exc)
    result = None
Defensive patterns

Strategy: try-catch

Validate before calling

def looks_like_video(data: bytes) -> bool:
    return data[:12].startswith((b'\x00\x00\x00\x18ftyp', b'\x1a45dfa3', b'RIFF')) or b'ftyp' in data[:64]

Type guard

def is_nonempty_bytes(data: object) -> TypeGuard[bytes]:
    return isinstance(data, bytes) and len(data) > 0

Try / catch

try:
    result = extract_video_frames(content, offset_seconds=0, duration_seconds=10, sampling_rate=1)
except VideoExtractionError as exc:
    logger.warning("Unopenable video payload: %s", exc)
    result = None

Prevention

When it happens

Trigger: Passing truncated, corrupted, or non-video bytes (HTML error page, text, partially downloaded MP4) to `extract_video_frames`; unsupported codec/container for the installed FFmpeg build.

Common situations: Download interrupted mid-file; an API returned a JSON error body stored as .mp4; a codec (e.g. newer H.266) the bundled FFmpeg cannot demux.

Related errors


AI-assisted analysis of langchain-ai/deepagents@a1af029e6e (2026-08-29). Data as JSON: /api/errors/46f957bd16076f6e. Report an issue: GitHub.