unclecode/crawl4ai · error · HTTPException
Artifact not found
Error message
Artifact not found
What it means
A 404 from GET /artifacts/{artifact_id}: resolve_artifact() raised ArtifactNotFound — no artifact with that id exists in the sandboxed store. Ids are opaque, so any typo, expired/evicted artifact, or wrong server yields this.
Source
Thrown at deploy/docker/server.py:657
raise HTTPException(413, "Artifact too large")
except QuotaExceeded:
raise HTTPException(507, "Artifact storage quota exceeded")
return {
"artifact_id": meta["artifact_id"],
"url": f"/artifacts/{meta['artifact_id']}",
"mime": meta["mime"],
"size": meta["size"],
}
@app.get("/artifacts/{artifact_id}")
async def get_artifact(artifact_id: str, _td: Dict = Depends(token_dep)):
"""Fetch a previously generated artifact by its opaque id (authed)."""
from artifacts import resolve_artifact, ArtifactNotFound
try:
path, mime = resolve_artifact(artifact_id)
except ArtifactNotFound:
raise HTTPException(404, "Artifact not found")
return FileResponse(path, media_type=mime, headers={"X-Content-Type-Options": "nosniff"})
# Screenshot endpoint
@app.post("/screenshot")
@limiter.limit(config["rate_limiting"]["default_limit"])
@mcp_tool("screenshot")
async def generate_screenshot(
request: Request,
body: ScreenshotRequest,
_td: Dict = Depends(token_dep),
):
"""
Capture a full-page PNG screenshot of the specified URL, waiting an optional delay before capture.
Use when you need an image snapshot of the rendered page. The image is also written to the
sandboxed artifact store; the response includes an `artifact_id` and a `url` to fetch it.View on GitHub (pinned to 7e80152142)
Solutions
- Verify the artifact_id against the one returned in the original response body (fields artifact_id / url).
- If artifacts are needed later, back the store with a persistent volume or shared storage across replicas.
- Re-generate the artifact by re-running the /screenshot or /pdf call.
- Treat 404 as terminal in clients — regenerate rather than retry the fetch.
Example fix
# client
resp = requests.get(f'{base}/artifacts/{art["artifact_id"]}')
if resp.status_code == 404:
art = requests.post(f'{base}/pdf', json={'url': url}, headers=auth).json() # regenerate Defensive patterns
Strategy: fallback
Try / catch
resp = requests.get(f'{BASE}/artifacts/{art_id}', headers=hdrs)
if resp.status_code == 404:
# regenerate instead of retrying the fetch
art = requests.post(f'{BASE}/screenshot', json={'url': url}, headers=hdrs).json()
art_id = art['artifact_id']
resp = requests.get(f'{BASE}/artifacts/{art_id}', headers=hdrs) Prevention
- Persist the artifact bytes you care about; don't rely on server-side retention.
- Back the store with a persistent volume if artifacts must survive restarts.
- Treat 404 as permanent — regenerate rather than retry.
When it happens
Trigger: GET /artifacts/<id> where the id was mistyped, the artifact was deleted/pruned after quota pressure, the service restarted with a non-persistent store volume, or the request hit a different container instance than the one that wrote it.
Common situations: Multi-replica deployments without shared artifact storage; artifacts stored in container-local tmpfs lost on restart; copy-paste truncation of long ids; retention jobs pruning old artifacts.
Related errors
- Artifact too large
- Artifact storage quota exceeded
- Timeout after {timeout}ms waiting for selector '{css_selecto
- Invalid CSS selector: '{css_selector}'
- Timeout after {timeout}ms waiting for selector '{wait_for}'
AI-assisted analysis of unclecode/crawl4ai@7e80152142 (2026-08-14).
Data as JSON: /api/errors/187331d79783230c.
Report an issue: GitHub.