{"record":{"id":"019e8807d157a035","repo":"abi/screenshot-to-code","slug":"error-capturing-screenshot-str-e","errorCode":null,"errorMessage":"Error capturing screenshot: {str(e)}","messagePattern":"Error capturing screenshot: (.+?)","errorType":"http","errorClass":"HTTPException","httpStatus":500,"severity":"error","filePath":"backend/routes/screenshot.py","lineNumber":107,"sourceCode":"    api_key = request.apiKey\n\n    try:\n        # Normalize the URL\n        normalized_url = normalize_url(url)\n        \n        # Capture screenshot with normalized URL\n        image_bytes = await capture_screenshot(normalized_url, api_key=api_key)\n\n        # Convert the image bytes to a data url\n        data_url = bytes_to_data_url(image_bytes, \"image/png\")\n\n        return ScreenshotResponse(url=data_url)\n    except ValueError as e:\n        # Handle URL normalization errors\n        raise HTTPException(status_code=500, detail=str(e))\n    except Exception as e:\n        # Handle other errors\n        raise HTTPException(status_code=500, detail=f\"Error capturing screenshot: {str(e)}\")\n","sourceCodeStart":89,"sourceCodeEnd":108,"githubUrl":"https://github.com/abi/screenshot-to-code/blob/d026163f586dfa8c5c10d28c36edd59a9d3b0e88/backend/routes/screenshot.py#L89-L108","documentation":"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.","triggerScenarios":"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.","commonSituations":"No outbound network access from the backend container; screenshotone key invalid; target host unreachable; slow page exceeding the 60-second httpx timeout.","solutions":["Read the detail substring: 'Error taking screenshot' means upstream rejected the request — validate the apiKey and quota (see error 84)","If the detail names httpx.ConnectError/ConnectTimeout: check outbound network/DNS from the backend host","If httpx.ReadTimeout: retry once, or raise the httpx timeout in capture_screenshot beyond 60s","Reproduce with the same URL from a working environment to isolate target-specific blocking"],"exampleFix":"# before\nresp = await client.post(\"/api/screenshot\", json=req)\nif resp.status_code >= 400:\n    raise RuntimeError(resp.text)  # loses cause\n\n# after (structured handling)\ntry:\n    resp = await client.post(\"/api/screenshot\", json=req)\n    resp.raise_for_status()\nexcept httpx.HTTPStatusError:\n    detail = resp.json().get(\"detail\", \"\")\n    if \"Unsupported protocol\" in detail:\n        raise ValueError(f\"Bad URL: {url}\")\n    raise RuntimeError(f\"Screenshot failed: {detail}\")","handlingStrategy":"try-catch","validationCode":"def preflight(url: str, api_key: str) -> None:\n    validate_screenshot_request(url, api_key)  # catches scheme/key issues client-side\n    socket.create_connection((urlparse(url).hostname, 443), timeout=5).close()  # egress check","typeGuard":null,"tryCatchPattern":"try:\n    shot = await take_screenshot(url)\nexcept httpx.HTTPStatusError as e:\n    detail = e.response.json().get(\"detail\", \"\")\n    if \"Error taking screenshot\" in detail:\n        handle_upstream_failure(detail)      # key/quota/target issue\n    elif \"timeout\" in detail.lower():\n        return await retry_with_backoff(take_screenshot, url)  # transient\n    else:\n        handle_network_failure(detail)","preventionTips":["Branch on the detail substring to separate upstream, network, and timeout causes","Retry only timeout/network failures; upstream auth failures need human action","Health-check outbound egress and the screenshotone key as part of app startup checks"],"tags":["fastapi","http-500","screenshot","error-handling"],"backgroundTag":null,"analyzedSha":"d026163f586dfa8c5c10d28c36edd59a9d3b0e88","analyzedAt":"2026-08-14T22:02:06.951Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}