{"record":{"id":"741355a4e2f7894c","repo":"odysseus-dev/odysseus","slug":"album-not-found","errorCode":null,"errorMessage":"Album not found","messagePattern":"Album not found","errorType":"http","errorClass":"HTTPException","httpStatus":404,"severity":"warning","filePath":"routes/gallery/gallery_routes.py","lineNumber":2127,"sourceCode":"            enhanced = img.filter(ImageFilter.MedianFilter(size=3))  # light denoise\n            enhanced = enhanced.filter(ImageFilter.UnsharpMask(radius=2, percent=150, threshold=3))  # sharpen\n            enhanced = ImageEnhance.Contrast(enhanced).enhance(1.15)  # slight contrast boost\n            enhanced = ImageEnhance.Color(enhanced).enhance(1.1)  # subtle color boost\n            enhanced = ImageEnhance.Brightness(enhanced).enhance(1.05)  # slight brightness lift\n\n            buf = io.BytesIO()\n            enhanced.save(buf, format=\"PNG\")\n            return {\"image\": base64.b64encode(buf.getvalue()).decode(), \"method\": \"pil\"}\n        except Exception:\n            logger.exception(\"enhance_face: failed\")\n            raise HTTPException(500, \"Face enhancement failed\")\n\n    # ---- Album management (path-param routes) ----\n\n    def _get_or_404_album(db, album_id: str, user):\n        album = db.query(GalleryAlbum).filter(GalleryAlbum.id == album_id).first()\n        if not album:\n            raise HTTPException(404, \"Album not found\")\n        if not user or album.owner != user:\n            raise HTTPException(404, \"Album not found\")\n        return album\n\n    def _get_or_404_image(db, image_id: str, user):\n        img = db.query(GalleryImage).filter(GalleryImage.id == image_id).first()\n        if not img:\n            raise HTTPException(404, \"Image not found\")\n        if not user or img.owner != user:\n            raise HTTPException(404, \"Image not found\")\n        return img\n\n    @router.put(\"/api/gallery/albums/{album_id}\")\n    async def update_album(request: Request, album_id: str):\n        user = get_current_user(request)\n        data = await request.json()\n        db = SessionLocal()\n        try:","sourceCodeStart":2109,"sourceCodeEnd":2145,"githubUrl":"https://github.com/odysseus-dev/odysseus/blob/f9235ebbf13f693a6fd29ce70b097f6ec83705bf/routes/gallery/gallery_routes.py#L2109-L2145","documentation":"HTTP 404 from _get_or_404_album when no GalleryAlbum row exists with the given album_id in the database. This is the 'does not exist' branch; the separate owner check (609) is the 'exists but not yours' branch, deliberately returning the same status and message to avoid leaking album existence.","triggerScenarios":"PUT/DELETE /api/gallery/albums/{album_id} (and image-in-album ops) with an ID from a deleted album, a stale client cache, or a typo/truncated UUID.","commonSituations":"Album deleted in another tab or by another session; client holds an old album list; database reset/re-migrated so IDs no longer resolve.","solutions":["Re-fetch the album list (GET /api/gallery/albums) and use a current ID","Treat 404 on album ops as 'refresh state' in the UI rather than an error dialog","Confirm the album was not deleted by another session sharing the account"],"exampleFix":"# client\nresp = requests.put(f'{base}/api/gallery/albums/{aid}', json=body)\nif resp.status_code == 404:\n    albums = requests.get(f'{base}/api/gallery/albums').json()  # refresh\n    aid = pick_album(albums)","handlingStrategy":"validation","validationCode":"def album_exists(album_id: str) -> bool:\n    albums = requests.get(f'{base}/api/gallery/albums', headers=hdrs, timeout=30).json()\n    return any(a.get('id') == album_id for a in albums.get('albums', albums))","typeGuard":null,"tryCatchPattern":"try:\n    update_album(album_id, name='Holiday')\nexcept HTTPError as e:\n    if e.response.status_code == 404:\n        albums = refresh_album_cache()\n        album_id = first(a['id'] for a in albums if a['name'] == 'Holiday') or create_album('Holiday')\n        update_album(album_id, name='Holiday')\n    else:\n        raise","preventionTips":["Refresh the album list after any delete event or tab focus change before issuing mutations","Treat 404 on album routes as a UI state-refresh trigger, not a hard error","Note that IDs are UUID-like strings — validate format client-side to catch truncation"],"tags":["http-404","gallery","album","not-found","crud"],"backgroundTag":null,"analyzedSha":"f9235ebbf13f693a6fd29ce70b097f6ec83705bf","analyzedAt":"2026-08-14T21:47:48.359Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}