fix: surface actionable delete-failure messages instead of a bare HTTP 500#352
Merged
Conversation
…P 500
Deleting an image from a read-only folder popped a dialog reading
"Failed to delete: HTTP 500 Internal Server Error for delete_image/..."
— the server knew it was a permissions problem but the reason never
reached the user.
Backend: the file-removal step of delete_image now translates OS
failures into HTTP errors with actionable detail — PermissionError
becomes a 403 naming the file and pointing at write permissions;
send2trash's TrashPermissionError becomes a 403 suggesting the
'Just Delete' setting (the file may be deletable even when the trash
folder isn't usable); other OSErrors keep the 500 but carry the OS
reason and the same Settings hint when trashing was the failure.
Frontend: new errorDetail() helper in utils.js prefers the server's
{detail: ...} explanation over HttpError's generic message; the delete
alerts in control-panel.js and bookmarks.js use it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
lstein
enabled auto-merge (rebase)
July 16, 2026 20:31
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Deleting an image the server can't remove (e.g. a read-only folder) popped a dialog reading:
Two failures stacked: the backend wrapped the
PermissionErrorin a generic 500, and the frontend showedHttpError.messagewhile the server's explanation sat unread inerror.body.detail. This fixes both halves.Changes
Backend (
routers/index.py)_remove_image_file()helper wraps the trash/unlink step ofdelete_imageand translates OS failures into HTTP errors whosedetailtells the user what to fix:PermissionError→ 403 — "Cannot delete 'img.jpg': permission denied. The PhotoMap server needs write permission on the image file and its containing folder."TrashPermissionError→ 403 — the file may be deletable even though the trash folder isn't usable, so the message suggests switching "When deleting" to "Just Delete" in Settings.OSError→ 500, but the detail now carries the OS reason (e.g. "Invalid cross-device link" from the known no-trash-dir-on-mount case) plus the same Settings hint when trashing was what failed.Frontend
errorDetail(error)helper inutils.jsprefers the server's{detail: "..."}string over the genericHTTP <status> for <url>message (string details only — FastAPI validation lists fall back to the generic message).control-panel.jsandbookmarks.jsuse it.Testing
PermissionError→ 403 naming the file (and confirming the failed delete leaves file + index row intact),TrashPermissionError→ 403 with the Settings suggestion, generic trashOSError→ 500 carrying the OS reason.errorDetail(prefers detail; falls back for missing/non-string detail and non-HTTP errors).Follow-up
Once this and #351 are both merged, the batch
delete_imagesendpoint's per-itemerrorslist (currently raw exception strings) should reuse_remove_image_file()for the same actionable wording.🤖 Generated with Claude Code