NousResearch/hermes-agent · error · ValueError
Image at {url} returned 0 bytes; refusing to cache.
Error message
Image at {url} returned 0 bytes; refusing to cache. What it means
Raised by the image-generation provider's cache writer after streaming an image from a remote URL produced zero bytes. The empty file is unlinked and the download is aborted so a 0-byte artifact never poisons the cache. It signals that the provider URL responded but delivered no body (or the read loop received no chunks).
Source
Thrown at agent/image_gen_provider.py:342
continue
bytes_written += len(chunk)
if bytes_written > max_bytes:
fh.close()
try:
path.unlink()
except OSError:
pass
raise ValueError(
f"Image 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"Image at {url} returned 0 bytes; refusing to cache.")
return path
def success_response(
*,
image: str,
model: str,
prompt: str,
aspect_ratio: str,
provider: str,
modality: str = "text",
extra: Optional[Dict[str, Any]] = None,
) -> Dict[str, Any]:
"""Build a uniform success response dict.
``image`` may be an HTTP URL or an absolute filesystem path (for b64
providers like OpenAI). ``modality`` is ``"text"`` (text-to-image) orView on GitHub (pinned to c896c09c42)
Solutions
- Retry the generation once — transient empty-body responses from image providers usually succeed on a second call.
- Verify the URL is fresh: if the provider hands back short-lived signed URLs, re-request the image metadata to obtain a new URL before downloading.
- Check with curl -I <url> that the URL actually returns Content-Length > 0 and a 200; if it 403s or redirects, fix the provider credentials/redirect handling.
- Inspect provider API docs/changelog for response-format changes (e.g. b64_json vs url) and update the response parsing.
Example fix
// before
const result = await provider.generate({ prompt });
await cacheImage(result.url); // throws ValueError: 0 bytes
// after
const result = await provider.generate({ prompt });
const head = await fetch(result.url, { method: 'HEAD' });
if (!head.ok || Number(head.headers.get('content-length') ?? 0) === 0) {
throw new Error(`provider returned empty image at ${result.url}; retry generation`);
}
await cacheImage(result.url); Defensive patterns
Strategy: retry
Validate before calling
import urllib.request
def image_url_has_content(url: str) -> bool:
req = urllib.request.Request(url, method="HEAD")
with urllib.request.urlopen(req, timeout=10) as resp:
return resp.status == 200 and int(resp.headers.get("Content-Length") or 0) > 0 Try / catch
try:
path = cache_image(url)
except ValueError as e:
if "0 bytes" in str(e):
path = cache_image(refresh_image_url(url)) # one retry with a fresh URL
else:
raise Prevention
- Re-check signed URLs for freshness before downloading; short-lived URLs are the top cause of empty bodies.
- HEAD-check Content-Length > 0 before handing the URL to the cache writer.
- Log the provider response status and headers when a download fails so empty 200s are distinguishable from auth failures.
When it happens
Trigger: Calling the image cache/download path (e.g. image_gen tool with a provider that returns a URL) where the HTTP response body is empty: a signed URL that expired and returns 200 with no content, a redirect handled without follow, or a provider that streams zero chunks before closing.
Common situations: Expired or mis-scoped presigned S3/GCS URLs; provider API changes returning metadata instead of bytes; proxies or gateways stripping the body; transient provider outages that return 200-empty.
Related errors
- Preview mode — launching is disabled.
- no install root
- ${isPosix ? 'install.sh --manifest' : 'install.ps1 -Manifest
- Remote connection is not ready yet. Try again in a moment.
- Remote gateway URL is required.
AI-assisted analysis of NousResearch/hermes-agent@c896c09c42 (2026-08-14).
Data as JSON: /api/errors/d6fdd03e4de6a66b.
Report an issue: GitHub.