{"record":{"id":"7b41e1ef1bb8ec6c","repo":"odysseus-dev/odysseus","slug":"failed-to-fetch-gallery-library","errorCode":null,"errorMessage":"Failed to fetch gallery library","messagePattern":"Failed to fetch gallery library","errorType":"http","errorClass":"HTTPException","httpStatus":500,"severity":"critical","filePath":"routes/gallery/gallery_routes.py","lineNumber":806,"sourceCode":"                    q = q.order_by(GalleryImage.created_at.asc())\n                else:  # recent\n                    q = q.order_by(GalleryImage.created_at.desc())\n                rows = q.offset(offset).limit(limit).all()\n\n            items = []\n            for img, session_name in rows:\n                items.append(_image_to_dict(img, session_name))\n\n            return {\n                \"items\": items,\n                \"total\": total,\n                \"total_tagged\": total_tagged,\n                \"tags\": sorted(all_tags),\n                \"models\": all_models,\n            }\n        except Exception:\n            logger.exception(\"Failed to fetch gallery library\")\n            raise HTTPException(500, \"Failed to fetch gallery library\")\n        finally:\n            db.close()\n\n    # ---- Album CRUD (must be before {image_id} catch-all) ----\n\n    @router.get(\"/api/gallery/albums\")\n    async def list_albums(request: Request):\n        user = get_current_user(request)\n        db = SessionLocal()\n        try:\n            q = db.query(GalleryAlbum)\n            q = _owner_filter(q, user, GalleryAlbum)\n            albums = q.order_by(GalleryAlbum.created_at.desc()).all()\n            result = []\n            for a in albums:\n                _count_q = db.query(GalleryImage).filter(\n                    GalleryImage.album_id == a.id, GalleryImage.is_active == True\n                )","sourceCodeStart":788,"sourceCodeEnd":824,"githubUrl":"https://github.com/odysseus-dev/odysseus/blob/f9235ebbf13f693a6fd29ce70b097f6ec83705bf/routes/gallery/gallery_routes.py#L788-L824","documentation":"HTTP 500 raised by GET of the gallery library endpoint when the broad try/except around the query/aggregation block catches any exception. The handler logs 'Failed to fetch gallery library' with a full traceback and re-raises as a generic 500. Because the except is untyped, causes range from SQL errors to failures inside _image_to_dict.","triggerScenarios":"Schema drift (columns like tags/models missing after an upgrade without migration), a corrupted row that breaks _image_to_dict, DB connection loss, or an aggregation query failing on unexpected NULLs.","commonSituations":"Upgrading the app without running migrations; SQLite file locked by a backup job; a row with NULL in a field the serializer assumes is present.","solutions":["Read the server log — the logger.exception traceback names the actual failing operation.","If it is schema drift, run the project's migrations so GalleryImage/DbSession columns match the ORM.","If it is a bad row, identify and repair/delete it based on the traceback.","Restart after DB maintenance; retry once the connection is stable."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"try { return await fetchLibrary(); }\ncatch (e) {\n  if (e.status !== 500) throw e;\n  await sleep(1000);\n  return await fetchLibrary(); // single retry for transient DB issues\n}","preventionTips":["Run migrations after every upgrade","Keep DB connections alive / tune pool","Monitor server logs for the 'Failed to fetch gallery library' traceback to find root cause","Back up DB and gallery files together"],"tags":["http","database","gallery","server-error","schema"],"backgroundTag":null,"analyzedSha":"f9235ebbf13f693a6fd29ce70b097f6ec83705bf","analyzedAt":"2026-08-14T21:47:48.359Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}