Skip to content

fix(gallery): traverse image subfolders when finding orphaned db entries#9291

Open
lstein wants to merge 1 commit into
mainfrom
fix/gallery-maintenance-subfolder-traversal
Open

fix(gallery): traverse image subfolders when finding orphaned db entries#9291
lstein wants to merge 1 commit into
mainfrom
fix/gallery-maintenance-subfolder-traversal

Conversation

@lstein

@lstein lstein commented Jun 16, 2026

Copy link
Copy Markdown
Collaborator

Summary

Fixes data loss in scripts/gallery_maintenance.py (logic in invokeai/backend/util/gallery_maintenance.py) when an image_subfolder_strategy is configured.

When invokeai.yaml sets an image_subfolder_strategy (date, type, or hash), new images are written into subfolders of outputs/images (e.g. outputs/images/2026/03/17/<name>.png). The Clean Orphaned Database Entries operation only checked the top-level outputs/images directory for each image, so every image living in a subfolder appeared to be missing — and its perfectly valid database row was deleted. Users reported thousands of entries being wrongly removed.

Fix

  • Add PhysicalFileMapper.get_all_image_filenames_recursive(), which globs the entire outputs/images tree (**/*.png) and returns the set of all image basenames found anywhere.
  • Use that index in clean_orphaned_db_entries: a DB row is now only considered orphaned if its file is absent from the whole tree, not just the top level.

Why this is safe:

  • Image names are globally unique UUIDs, so a set keyed by basename is collision-free across subfolders.
  • Thumbnails are .webp and are excluded by the .png glob.
  • The images-archive directory is a sibling of images/, so it is not traversed.
  • Building the index once and doing O(1) lookups is also faster than the previous per-row os.path.exists stat calls.

Scope is intentionally limited to the orphaned-DB-entry operation, which is the one that destructively deletes database rows. The archive/thumbnail operations only move or create files and were left unchanged to avoid surprising side effects.

Testing

  • python3 -m py_compile passes.
  • Verified the recursive glob against a representative tree: flat, date-subfolder, and hash-subfolder images are all found; .webp thumbnails and the sibling images-archive directory are correctly excluded.

🤖 Generated with Claude Code

When invokeai.yaml sets an image_subfolder_strategy, new images are written
into subfolders of outputs/images (by date, type, or hash). The orphaned-db-
entry cleanup only checked the top-level outputs/images directory, so every
image stored in a subfolder looked missing and its (valid) database row was
deleted.

Add PhysicalFileMapper.get_all_image_filenames_recursive(), which globs the
entire outputs/images tree, and use it for the orphan check. Image names are
globally unique UUIDs, so a basename set is collision-free; thumbnails (.webp)
and the sibling images-archive directory are naturally excluded.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot added python PRs that change python files backend PRs that change backend files labels Jun 16, 2026
@lstein lstein added the 6.13.5 Library Updates label Jun 16, 2026
@lstein lstein moved this to 6.13.5 LIBRARY UPDATES in Invoke - Community Roadmap Jun 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

6.13.5 Library Updates backend PRs that change backend files python PRs that change python files

Projects

Status: 6.13.5 LIBRARY UPDATES

Development

Successfully merging this pull request may close these issues.

2 participants