unslothai/unsloth · error · HTTPException
Image not found.
Error message
Image not found.
What it means
HTTP 404 from the dataset image serving route: the dataset folder resolved and the filename passed all safety checks, but image_path.is_file() is false — the named image does not exist (deleted, renamed, or never uploaded). Raised before thumbnail generation, so no thumb is produced either.
Source
Thrown at studio/backend/routes/training.py:3817
return await asyncio.to_thread(scan)
@router.get("/diffusion/dataset/{name}/image/{filename}")
async def get_diffusion_dataset_image(
name: str,
filename: str,
thumb: Optional[int] = None,
current_subject: str = Depends(get_current_subject),
):
"""Serve a dataset image. ``?thumb=<px>`` returns a cached downscaled JPEG (regenerated
when the source is newer), used by the labeling grid to stay light."""
from fastapi.responses import FileResponse
folder = _resolve_dataset_folder(name)
image_path = _safe_dataset_image_path(folder, filename)
if not image_path.is_file():
raise HTTPException(status_code = 404, detail = "Image not found.")
if not thumb:
return FileResponse(str(image_path))
size = max(32, min(1024, int(thumb)))
def make_thumb() -> Path:
from PIL import Image
thumbs_dir = folder / _THUMBS_DIRNAME
thumbs_dir.mkdir(exist_ok = True)
# Key on the full filename, not the stem: two images sharing a stem would collide on one cache file and the mtime-newer entry would be served for both.
thumb_path = thumbs_dir / f"{image_path.name}_{size}.jpg"
src_mtime = image_path.stat().st_mtime
if thumb_path.is_file() and thumb_path.stat().st_mtime >= src_mtime:
return thumb_path
with Image.open(image_path) as im:
im = im.convert("RGB")
im.thumbnail((size, size), Image.LANCZOS)View on GitHub (pinned to 203007d190)
Solutions
- Refresh the dataset image list (GET /diffusion/dataset/{name}/images) and use current filenames.
- If the file was renamed, use the new name; if deleted, re-upload it.
- Cache-bust or expire stale client asset URLs after delete operations.
Example fix
// before
<img src={`/training/diffusion/dataset/${name}/image/${fname}?thumb=256`} />
// after — verify existence first / on error remove from grid
const imgs = await api.listImages(name);
const ok = imgs.some(i => i.name === fname); Defensive patterns
Strategy: validation
Validate before calling
from pathlib import Path
def image_served(folder: Path, filename: str) -> bool:
return (folder / filename).is_file() Type guard
def is_image_not_found(exc: HTTPException) -> bool:
return exc.status_code == 404 and exc.detail == 'Image not found.' Try / catch
try:
r = await client.get(image_url)
except httpx.HTTPStatusError as e:
if e.response.status_code == 404:
removeFromGrid(filename) # prune stale entry, don't retry
return
raise Prevention
- After a delete/import, re-fetch the image list before rendering grids.
- On 404, drop the entry from the UI instead of retrying — the file is gone.
When it happens
Trigger: GET /training/diffusion/dataset/{name}/image/{filename} where the file is absent: a labeling grid holding stale URLs after images were deleted in another tab, a renamed file, or a typo'd filename.
Common situations: Two tabs editing one dataset (delete in one, grid in the other); scripts referencing files after a re-import replaced the set; client caches serving old asset URLs; case-sensitivity mismatch on case-folding filesystems.
Related errors
- Dataset '{cleaned}' not found.
- Unknown example dataset '{example_id}'.
- Image '{original_name}' is too large ({width}x{height}); max
- lockfile not found: {path}
- Invalid base64 image data: {exc}
AI-assisted analysis of unslothai/unsloth@203007d190 (2026-08-15).
Data as JSON: /api/errors/5238b4b36627d396.
Report an issue: GitHub.