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

  1. Verify the artifact_id against the one returned in the original response body (fields artifact_id / url).
  2. If artifacts are needed later, back the store with a persistent volume or shared storage across replicas.
  3. Re-generate the artifact by re-running the /screenshot or /pdf call.
  4. 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

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


AI-assisted analysis of unclecode/crawl4ai@7e80152142 (2026-08-14). Data as JSON: /api/errors/187331d79783230c. Report an issue: GitHub.