{"record":{"id":"8596a1ba15ec3f60","repo":"odysseus-dev/odysseus","slug":"album-name-required","errorCode":null,"errorMessage":"Album name required","messagePattern":"Album name required","errorType":"http","errorClass":"HTTPException","httpStatus":400,"severity":"warning","filePath":"routes/gallery/gallery_routes.py","lineNumber":857,"sourceCode":"                    if first:\n                        cover_url = f\"/api/generated-image/{first.filename}\"\n                result.append({\n                    \"id\": a.id, \"name\": a.name, \"description\": a.description or \"\",\n                    \"cover_url\": cover_url, \"count\": count,\n                    \"created_at\": a.created_at.isoformat() if a.created_at else None,\n                })\n            return {\"albums\": result}\n        finally:\n            db.close()\n\n    @router.post(\"/api/gallery/albums\")\n    async def create_album(request: Request):\n        import uuid\n        user = get_current_user(request)\n        data = await request.json()\n        name = (data.get(\"name\") or \"\").strip()\n        if not name:\n            raise HTTPException(400, \"Album name required\")\n        db = SessionLocal()\n        try:\n            a = GalleryAlbum(\n                id=str(uuid.uuid4()), name=name,\n                description=data.get(\"description\", \"\"),\n                owner=user,\n            )\n            db.add(a)\n            db.commit()\n            return {\"ok\": True, \"id\": a.id, \"name\": a.name}\n        finally:\n            db.close()\n\n    @router.get(\"/api/gallery/stats\")\n    async def gallery_stats(request: Request):\n        user = get_current_user(request)\n        db = SessionLocal()\n        try:","sourceCodeStart":839,"sourceCodeEnd":875,"githubUrl":"https://github.com/odysseus-dev/odysseus/blob/f9235ebbf13f693a6fd29ce70b097f6ec83705bf/routes/gallery/gallery_routes.py#L839-L875","documentation":"HTTP 400 raised by POST /api/gallery/albums when the album name is empty after trimming. The handler strips data['name'] and rejects blank, missing, or null values before creating the GalleryAlbum row.","triggerScenarios":"POST /api/gallery/albums with {}, {\"name\": \"\"}, {\"name\": \"  \"}, or {\"name\": null}.","commonSituations":"Creating an album from an empty dialog; frontend sending 'title' instead of 'name'; double submits clearing the field.","solutions":["Require non-blank input in the album-creation form.","Send the key as exactly \"name\".","Trim client-side and skip the request when empty."],"exampleFix":"// before\nawait post('/api/gallery/albums', {title: v}); // wrong key -> 400\n// after\nconst name = v.trim(); if (!name) return;\nawait post('/api/gallery/albums', {name, description: ''});","handlingStrategy":"validation","validationCode":"const name = (input?.value ?? '').trim();\nif (!name) return showError('Album name is required');\nawait post('/api/gallery/albums', {name});","typeGuard":"const isNonBlankAlbumName = (v) => typeof v === 'string' && v.trim().length > 0;","tryCatchPattern":null,"preventionTips":["Use the exact key 'name'","Require the field in the create-album form","Trim input client-side"],"tags":["http","validation","gallery","album"],"backgroundTag":null,"analyzedSha":"f9235ebbf13f693a6fd29ce70b097f6ec83705bf","analyzedAt":"2026-08-14T21:47:48.359Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}