abi/screenshot-to-code · warning · HTTPException

Image not found

Error message

Image not found

What it means

Raised by GET /eval-sets/{set_name}/images/{filename} (404) when the set and inputs/ directory exist and the filename passed the .png check, but no file with that name is on disk (resolve_set_image_path raises FileNotFoundError at sets.py:302). It is the plain missing-file case.

Source

Thrown at backend/routes/eval_sets.py:179

                sha256=image.sha256,
                size_bytes=image.size_bytes,
                tags=image.tags,
            )
            for image in images
        ],
    )


@router.get("/eval-sets/{set_name}/images/{filename}")
async def get_eval_set_image(set_name: str, filename: str) -> FileResponse:
    try:
        path = eval_sets.resolve_set_image_path(set_name, filename)
    except eval_sets.InvalidSetNameError as e:
        raise HTTPException(status_code=400, detail=str(e))
    except eval_sets.EvalSetNotFoundError:
        raise HTTPException(status_code=404, detail=f"Eval set not found: {set_name}")
    except FileNotFoundError:
        raise HTTPException(status_code=404, detail="Image not found")
    return FileResponse(path)


@router.get("/eval-sessions", response_model=EvalSessionListResponse)
async def list_eval_sessions() -> EvalSessionListResponse:
    sessions = eval_sessions.list_sessions()
    active = next((s for s in sessions if s.is_active), None)
    return EvalSessionListResponse(
        sessions=[_session_to_model(s) for s in sessions],
        active_session_id=active.session_id if active else None,
    )


@router.get("/eval-sessions/active", response_model=Optional[EvalSessionModel])
async def get_active_eval_session() -> Optional[EvalSessionModel]:
    active = eval_sessions.get_active_session()
    return _session_to_model(active) if active else None

View on GitHub (pinned to d026163f58)

Solutions

  1. List the set's actual images via GET /eval-sets/{set_name} and use an exact filename.
  2. Check case: the extension check is case-insensitive but the filesystem lookup is exact.
  3. Restore or re-add the missing image to inputs/ if a manifest still references it.

Example fix

# before
GET /eval-sets/my-set/images/hero01.png  # 404 'Image not found'

# after
detail = requests.get(url + "/eval-sets/my-set").json()
fname = detail["images"][0]["filename"]
GET /eval-sets/my-set/images/{fname}
Defensive patterns

Strategy: validation

Validate before calling

detail = requests.get(url + f"/eval-sets/{set_name}").json()
known = {i["filename"] for i in detail.get("images", [])}
if filename not in known:
    raise LookupError(f"{filename!r} not among {sorted(known)}")

Type guard

def image_in_set(filename: str, detail: dict) -> bool:
    return any(i.get("filename") == filename for i in detail.get("images", []))

Try / catch

resp = requests.get(url + f"/eval-sets/{set_name}/images/{filename}")
if resp.status_code == 404 and "Image not found" in resp.text:
    filename = next(i["filename"] for i in requests.get(url + f"/eval-sets/{set_name}").json()["images"])
    resp = requests.get(url + f"/eval-sets/{set_name}/images/{filename}")
resp.raise_for_status()

Prevention

When it happens

Trigger: Requesting 'missing.png' for a set whose inputs directory lacks that file — typo, wrong set, or a file listed in a stale manifest that was deleted from disk.

Common situations: Manifest/filenames out of sync with disk after manual deletion; case-sensitivity mismatch (Shot.PNG vs shot.png on Linux); copying URLs between sets.

Related errors


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