{"record":{"id":"a998175cc2f8a61f","repo":"odysseus-dev/odysseus","slug":"cleanup-operation-failed","errorCode":null,"errorMessage":"Cleanup operation failed","messagePattern":"Cleanup operation failed","errorType":"http","errorClass":"HTTPException","httpStatus":500,"severity":"error","filePath":"routes/cleanup/cleanup_routes.py","lineNumber":58,"sourceCode":"        \"\"\"\n        Perform cleanup operations:\n        1. Archive inactive sessions (not accessed for 7 days)\n        2. Delete old sessions (archived, not important, not accessed for 14+ days, with fewer than 10 messages)\n\n        Returns:\n            JSON response with counts of deleted and archived sessions, and space freed\n        \"\"\"\n        user = get_current_user(request)\n        try:\n            archived_count, deleted_count, space_freed_mb = await cleanup_sessions(session_manager, owner=user)\n            return {\n                \"archived_count\": archived_count,\n                \"deleted_count\": deleted_count,\n                \"space_freed_mb\": round(space_freed_mb, 2)\n            }\n        except Exception as e:\n            logger.error(f\"Cleanup failed: {e}\")\n            raise HTTPException(500, \"Cleanup operation failed\")\n\n    return router\n","sourceCodeStart":40,"sourceCodeEnd":61,"githubUrl":"https://github.com/odysseus-dev/odysseus/blob/f9235ebbf13f693a6fd29ce70b097f6ec83705bf/routes/cleanup/cleanup_routes.py#L40-L61","documentation":"Raised as HTTP 500 by the POST cleanup endpoint when cleanup_sessions(session_manager, owner=user) throws; the cause is logged as 'Cleanup failed: <e>' first. Unlike the preview, this endpoint mutates state, so a 500 may mean the operation failed partway — some sessions may already be archived/deleted before the exception.","triggerScenarios":"POSTing the cleanup endpoint when archive/delete operations fail: file permission errors deleting session dirs, DB errors updating archived flags, or an unexpected session object shape mid-iteration.","commonSituations":"Read-only or root-owned session files after restoring from backup; concurrent cleanup runs racing on the same sessions; DB locked by another writer; the preview succeeded but disk filled between preview and execution.","solutions":["Check server logs for the 'Cleanup failed' entry to identify the failing phase (archive vs delete).","Fix filesystem permissions on the sessions directory so the server user can move/delete files.","Re-run the preview endpoint afterwards and reconcile counts — partial completion is possible; a second POST is idempotent for already-archived sessions.","Ensure only one cleanup runs at a time (avoid double-clicking / parallel schedulers)."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"const preview = await fetch('/api/cleanup/preview');\nif (!preview.ok) { /* do not run destructive cleanup when preview fails */ }","typeGuard":null,"tryCatchPattern":"try {\n  result = await api.runCleanup();\n} catch (e) {\n  if (e.status === 500) {\n    const p = await api.getCleanupPreview(); // reconcile partial completion\n    report('Cleanup failed partway', p);\n    return;\n  }\n  throw e;\n}","preventionTips":["Gate the destructive POST on a successful preview response.","Run only one cleanup at a time; disable double-submit in the UI.","After any 500, re-run preview to reconcile counts because archive/delete may have partially applied."],"tags":["http-500","cleanup","partial-failure","maintenance"],"backgroundTag":null,"analyzedSha":"f9235ebbf13f693a6fd29ce70b097f6ec83705bf","analyzedAt":"2026-08-14T21:47:48.359Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}