unslothai/unsloth · error · HTTPException
Could not save the change to this video.
Error message
Could not save the change to this video.
What it means
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.
Source
Thrown at studio/backend/routes/video.py:595
@router.patch("/video/gallery/{video_id}", response_model = GalleryVideo)
async def update_gallery_video_flags(
video_id: str,
patch: GalleryFlagsPatch,
current_subject: str = Depends(get_current_subject),
):
"""Pin/unpin or archive/restore one clip. Omitted fields are left alone."""
from core.inference import video_gallery
try:
record = await asyncio.to_thread(
video_gallery.set_flags, video_id, pinned = patch.pinned, archived = patch.archived
)
except OSError as exc:
# The client already applied this optimistically, so a silent miss would look like it stuck
# and then quietly undo on reload.
logger.warning("video_gallery.set_flags_failed: %s", exc)
raise HTTPException(status_code = 500, detail = "Could not save the change to this video.")
if record is None:
raise HTTPException(status_code = 404, detail = "Video not found.")
# Archiving takes the clip off the strip, so the completed-job record must go with it: the page
# merges that snapshot on mount, which would keep resurrecting the clip it just archived.
if patch.archived:
_forget_terminal_video(video_id)
return GalleryVideo(**record)
@router.delete("/video/gallery/{video_id}")
async def delete_gallery_video(video_id: str, current_subject: str = Depends(get_current_subject)):
from core.inference import video_gallery
deleted = await asyncio.to_thread(video_gallery.delete, video_id)
if not deleted:
raise HTTPException(status_code = 404, detail = "Video not found.")
_forget_terminal_video(video_id)
return {"deleted": True}View on GitHub (pinned to 203007d190)
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).
Example fix
# diagnose $ df -h ~/.unsloth/studio # disk full? $ ls -la ~/.unsloth/studio/video-gallery* # permissions? # fix $ chown -R $(whoami) ~/.unsloth/studio
Defensive patterns
Strategy: try-catch
Try / catch
// optimistic UI must be revertible
const prev = clip.pinned;
clip.pinned = next;
try { await api.patch(`/video/gallery/${clip.id}`, { pinned: next }); }
catch (e) {
clip.pinned = prev; // roll back the optimistic change
toast('Could not save the change to this video.');
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Authorization flow was cancelled before credentials were sav
- Authorization flow was not found or expired.
- Failed to read the local dataset cache.
- Failed to delete dataset from {len(failures)} cache location
- Failed to check dataset format: {scrubbed}
AI-assisted analysis of unslothai/unsloth@203007d190 (2026-08-15).
Data as JSON: /api/errors/15cc820abd217e17.
Report an issue: GitHub.