NousResearch/hermes-agent · warning · ValueError

Video at {url} was empty (0 bytes).

Error message

Video at {url} was empty (0 bytes).

What it means

ValueError from agent/video_gen_provider.py:320: the streamed download of the generated video completed but wrote zero bytes, so the (empty) partial file is unlinked and the error raised. It distinguishes 'server returned nothing at this URL' from other failures.

Source

Thrown at agent/video_gen_provider.py:320

                continue
            bytes_written += len(chunk)
            if bytes_written > max_bytes:
                fh.close()
                try:
                    path.unlink()
                except OSError:
                    pass
                raise ValueError(
                    f"Video at {url} exceeds {max_bytes // (1024 * 1024)}MB cap; refusing to cache."
                )
            fh.write(chunk)

    if bytes_written == 0:
        try:
            path.unlink()
        except OSError:
            pass
        raise ValueError(f"Video at {url} was empty (0 bytes).")

    return path


def success_response(
    *,
    video: str,
    model: str,
    prompt: str,
    modality: str = "text",
    aspect_ratio: str = "",
    duration: int = 0,
    provider: str,
    extra: Optional[Dict[str, Any]] = None,
) -> Dict[str, Any]:
    """Build a uniform success response dict.

    ``video`` may be an HTTP URL or an absolute filesystem path.

View on GitHub (pinned to c896c09c42)

Solutions

  1. Verify the URL outside the app: curl -sL <url> -o /tmp/v && ls -l /tmp/v — 0 bytes confirms the provider side.
  2. Retry the download after a short delay (asset propagation lag right after job completion is the most common cause).
  3. Regenerate or re-request the asset URL if the signed link expired.
  4. If persistent, check the provider's status page / job logs for a partial-failure state.

Example fix

# before (single attempt, empty body aborts the whole generation)
path = _cache_video(url, max_bytes)

# after (one bounded retry for propagation lag)
for attempt in range(2):
    try:
        path = _cache_video(url, max_bytes)
        break
    except ValueError as exc:
        if "was empty" not in str(exc) or attempt == 1:
            raise
        time.sleep(5)
Defensive patterns

Strategy: retry

Validate before calling

import urllib.request

def url_has_body(url: str) -> bool:
    req = urllib.request.Request(url, method="HEAD")
    with urllib.request.urlopen(req, timeout=10) as r:
        length = r.headers.get("Content-Length")
        return length is None or int(length) > 0

Try / catch

for attempt in range(2):
    try:
        path = cache_video(url, max_bytes)
        return path
    except ValueError as exc:
        if "was empty" not in str(exc) or attempt == 1:
            raise
        time.sleep(5)  # asset propagation lag; retry once

Prevention

When it happens

Trigger: The video URL responds with an empty body — provider marked the job complete but the asset URL is not yet populated, a signed URL expired returning an empty 200, or a proxy/CDN hiccup delivered an empty stream.

Common situations: Racing a provider whose status turns 'completed' before the file is actually served; expired pre-signed S3/R2 URLs on retry; provider-side incident serving empty responses.

Related errors


AI-assisted analysis of NousResearch/hermes-agent@c896c09c42 (2026-08-14). Data as JSON: /api/errors/5d4ee0ce135ac15e. Report an issue: GitHub.