{"record":{"id":"15cc820abd217e17","repo":"unslothai/unsloth","slug":"could-not-save-the-change-to-this-video","errorCode":null,"errorMessage":"Could not save the change to this video.","messagePattern":"Could not save the change to this video\\.","errorType":"http","errorClass":"HTTPException","httpStatus":500,"severity":"error","filePath":"studio/backend/routes/video.py","lineNumber":595,"sourceCode":"\n@router.patch(\"/video/gallery/{video_id}\", response_model = GalleryVideo)\nasync def update_gallery_video_flags(\n    video_id: str,\n    patch: GalleryFlagsPatch,\n    current_subject: str = Depends(get_current_subject),\n):\n    \"\"\"Pin/unpin or archive/restore one clip. Omitted fields are left alone.\"\"\"\n    from core.inference import video_gallery\n\n    try:\n        record = await asyncio.to_thread(\n            video_gallery.set_flags, video_id, pinned = patch.pinned, archived = patch.archived\n        )\n    except OSError as exc:\n        # The client already applied this optimistically, so a silent miss would look like it stuck\n        # and then quietly undo on reload.\n        logger.warning(\"video_gallery.set_flags_failed: %s\", exc)\n        raise HTTPException(status_code = 500, detail = \"Could not save the change to this video.\")\n    if record is None:\n        raise HTTPException(status_code = 404, detail = \"Video not found.\")\n    # Archiving takes the clip off the strip, so the completed-job record must go with it: the page\n    # merges that snapshot on mount, which would keep resurrecting the clip it just archived.\n    if patch.archived:\n        _forget_terminal_video(video_id)\n    return GalleryVideo(**record)\n\n\n@router.delete(\"/video/gallery/{video_id}\")\nasync def delete_gallery_video(video_id: str, current_subject: str = Depends(get_current_subject)):\n    from core.inference import video_gallery\n\n    deleted = await asyncio.to_thread(video_gallery.delete, video_id)\n    if not deleted:\n        raise HTTPException(status_code = 404, detail = \"Video not found.\")\n    _forget_terminal_video(video_id)\n    return {\"deleted\": True}","sourceCodeStart":577,"sourceCodeEnd":613,"githubUrl":"https://github.com/unslothai/unsloth/blob/203007d19051dcd2ae33876786d117c99f6b0368/studio/backend/routes/video.py#L577-L613","documentation":"500 from the patch route: video_gallery.set_flags raised OSError while persisting the pin/archive flag — the flags store (a file/DB backing pin+archive state) could not be written. The comment explains the severity choice: the client applied the change optimistically, so silently swallowing the write failure would make the UI show a state that reverts on reload.","triggerScenarios":"PATCH /video/gallery/{id} with pinned/archived while the flags file is read-only, its directory was deleted, the disk is full, or a permission/lock problem (e.g. flags JSON on a synced/locked path) blocks the write.","commonSituations":"Studio data directory owned by root after running once under sudo; disk-full on a long-lived box; OneDrive/Dropbox-style sync holding a lock on the flags file; moving STUDIO_HOME without moving permissions.","solutions":["Check the server log line 'video_gallery.set_flags_failed: %s' — it carries the underlying OSError.","Fix the storage problem it names: chmod/chown the gallery data dir, free disk space, close the file locker.","After fixing, re-toggle the flag so the persistent state matches the UI (or reload to resync the UI to truth)."],"exampleFix":"# diagnose\n$ df -h ~/.unsloth/studio   # disk full?\n$ ls -la ~/.unsloth/studio/video-gallery*  # permissions?\n# fix\n$ chown -R $(whoami) ~/.unsloth/studio","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"// optimistic UI must be revertible\nconst prev = clip.pinned;\nclip.pinned = next;\ntry { await api.patch(`/video/gallery/${clip.id}`, { pinned: next }); }\ncatch (e) {\n  clip.pinned = prev;              // roll back the optimistic change\n  toast('Could not save the change to this video.');\n}","preventionTips":["Always pair optimistic UI with rollback on 5xx","Watch the server log's set_flags_failed line for the root OSError","Keep the gallery data dir writable by the service user; monitor disk space"],"tags":["http-500","oserror","persistence","optimistic-ui","disk-full"],"backgroundTag":null,"analyzedSha":"203007d19051dcd2ae33876786d117c99f6b0368","analyzedAt":"2026-08-15T02:48:39.846Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}