abi/screenshot-to-code · error · HTTPException

Error capturing screenshot

Error message

Error capturing screenshot: {str(e)}

What it means

Catch-all HTTPException(500, f"Error capturing screenshot: {e}") raised by /api/screenshot for any failure that is not a ValueError. In practice this wraps the generic "Error taking screenshot" Exception from capture_screenshot (screenshotone API non-200/empty) and httpx transport errors (DNS failure, connection refused, 60s timeout). The detail string echoes the original exception message, so its content tells you which layer failed.

Solutions

  1. Read the detail substring: 'Error taking screenshot' means upstream rejected the request — validate the apiKey and quota (see error 84)
  2. If the detail names httpx.ConnectError/ConnectTimeout: check outbound network/DNS from the backend host
  3. If httpx.ReadTimeout: retry once, or raise the httpx timeout in capture_screenshot beyond 60s
  4. Reproduce with the same URL from a working environment to isolate target-specific blocking

Example fix

# before
resp = await client.post("/api/screenshot", json=req)
if resp.status_code >= 400:
    raise RuntimeError(resp.text)  # loses cause

# after (structured handling)
try:
    resp = await client.post("/api/screenshot", json=req)
    resp.raise_for_status()
except httpx.HTTPStatusError:
    detail = resp.json().get("detail", "")
    if "Unsupported protocol" in detail:
        raise ValueError(f"Bad URL: {url}")
    raise RuntimeError(f"Screenshot failed: {detail}")
Defensive patterns

Strategy: try-catch

Validate before calling

def preflight(url: str, api_key: str) -> None:
    validate_screenshot_request(url, api_key)  # catches scheme/key issues client-side
    socket.create_connection((urlparse(url).hostname, 443), timeout=5).close()  # egress check

Try / catch

try:
    shot = await take_screenshot(url)
except httpx.HTTPStatusError as e:
    detail = e.response.json().get("detail", "")
    if "Error taking screenshot" in detail:
        handle_upstream_failure(detail)      # key/quota/target issue
    elif "timeout" in detail.lower():
        return await retry_with_backoff(take_screenshot, url)  # transient
    else:
        handle_network_failure(detail)

Prevention

When it happens

Trigger: POST /api/screenshot where the screenshotone call fails upstream (bad key, quota — detail contains 'Error taking screenshot') or the HTTP request itself fails (detail contains httpx.ConnectError/ReadTimeout); also bytes_to_data_url failures, though those are unlikely.

Common situations: No outbound network access from the backend container; screenshotone key invalid; target host unreachable; slow page exceeding the 60-second httpx timeout.

Related errors


AI-assisted analysis of abi/screenshot-to-code@d026163f58 (2026-08-14). Data as JSON: /api/errors/019e8807d157a035. Report an issue: GitHub.

Appendix: source

Thrown at backend/routes/screenshot.py:107

    api_key = request.apiKey

    try:
        # Normalize the URL
        normalized_url = normalize_url(url)
        
        # Capture screenshot with normalized URL
        image_bytes = await capture_screenshot(normalized_url, api_key=api_key)

        # Convert the image bytes to a data url
        data_url = bytes_to_data_url(image_bytes, "image/png")

        return ScreenshotResponse(url=data_url)
    except ValueError as e:
        # Handle URL normalization errors
        raise HTTPException(status_code=500, detail=str(e))
    except Exception as e:
        # Handle other errors
        raise HTTPException(status_code=500, detail=f"Error capturing screenshot: {str(e)}")

View on GitHub (pinned to d026163f58)