{"record":{"id":"5238b4b36627d396","repo":"unslothai/unsloth","slug":"image-not-found","errorCode":null,"errorMessage":"Image not found.","messagePattern":"Image not found\\.","errorType":"http","errorClass":"HTTPException","httpStatus":404,"severity":"error","filePath":"studio/backend/routes/training.py","lineNumber":3817,"sourceCode":"\n    return await asyncio.to_thread(scan)\n\n\n@router.get(\"/diffusion/dataset/{name}/image/{filename}\")\nasync def get_diffusion_dataset_image(\n    name: str,\n    filename: str,\n    thumb: Optional[int] = None,\n    current_subject: str = Depends(get_current_subject),\n):\n    \"\"\"Serve a dataset image. ``?thumb=<px>`` returns a cached downscaled JPEG (regenerated\n    when the source is newer), used by the labeling grid to stay light.\"\"\"\n    from fastapi.responses import FileResponse\n\n    folder = _resolve_dataset_folder(name)\n    image_path = _safe_dataset_image_path(folder, filename)\n    if not image_path.is_file():\n        raise HTTPException(status_code = 404, detail = \"Image not found.\")\n    if not thumb:\n        return FileResponse(str(image_path))\n\n    size = max(32, min(1024, int(thumb)))\n\n    def make_thumb() -> Path:\n        from PIL import Image\n\n        thumbs_dir = folder / _THUMBS_DIRNAME\n        thumbs_dir.mkdir(exist_ok = True)\n        # 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.\n        thumb_path = thumbs_dir / f\"{image_path.name}_{size}.jpg\"\n        src_mtime = image_path.stat().st_mtime\n        if thumb_path.is_file() and thumb_path.stat().st_mtime >= src_mtime:\n            return thumb_path\n        with Image.open(image_path) as im:\n            im = im.convert(\"RGB\")\n            im.thumbnail((size, size), Image.LANCZOS)","sourceCodeStart":3799,"sourceCodeEnd":3835,"githubUrl":"https://github.com/unslothai/unsloth/blob/203007d19051dcd2ae33876786d117c99f6b0368/studio/backend/routes/training.py#L3799-L3835","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\n<img src={`/training/diffusion/dataset/${name}/image/${fname}?thumb=256`} />\n// after — verify existence first / on error remove from grid\nconst imgs = await api.listImages(name);\nconst ok = imgs.some(i => i.name === fname);","handlingStrategy":"validation","validationCode":"from pathlib import Path\n\ndef image_served(folder: Path, filename: str) -> bool:\n    return (folder / filename).is_file()","typeGuard":"def is_image_not_found(exc: HTTPException) -> bool:\n    return exc.status_code == 404 and exc.detail == 'Image not found.'","tryCatchPattern":"try:\n    r = await client.get(image_url)\nexcept httpx.HTTPStatusError as e:\n    if e.response.status_code == 404:\n        removeFromGrid(filename)  # prune stale entry, don't retry\n        return\n    raise","preventionTips":["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."],"tags":["http-404","fastapi","dataset","image"],"backgroundTag":null,"analyzedSha":"203007d19051dcd2ae33876786d117c99f6b0368","analyzedAt":"2026-08-15T02:48:39.846Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}