Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
15 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ On a multi-user installation, only a board's owner or an administrator can delet

Right-click an item, or several selected items, for its menu.

<Image src={imageMenu} alt="The context menu for an image, with quick-action icons at the top followed by Load Workflow, Recall Metadata, Add to Current Canvas, New Project from Image, Send to Upscale, Send to Video, Use as Reference Image, Use as Prompt Template, Select for Compare, Find in Gallery, Change Board and Delete Image." width={420} />
<Image src={imageMenu} alt="The context menu for an image, with quick-action icons at the top followed by Load Workflow, Recall Metadata, Add to Current Canvas, New Project from Image, Send to Upscale, Send to Video, Use as Reference Image, Use as Prompt Template, Select for Compare, Generate PBR Maps, Find in Gallery, Change Board and Delete Image." width={420} />

For an image, the menu offers:

Expand All @@ -74,6 +74,7 @@ For an image, the menu offers:
* **Add to Current Canvas** — add the image to the open project's canvas as a new layer of the kind you choose.
* **New Project from Image** — start a new project whose canvas holds the image, sized to fit it.
* **Send to Upscale**, **Send to Video**, **Use as Reference Image**, **Use as Prompt Template** and **Select for Compare** — use the image elsewhere in InvokeAI.
* **Generate PBR Maps** — queue normal, roughness and displacement maps of the image. They are saved to the board the Gallery is auto-adding to, or to the project's Inbox if you can't add to that board (Uncategorized when there is neither), and a notice reports when they are ready. The first run downloads the PBR models.
* **Change Board** and **Delete Image**.

A video's menu has the equivalent actions for video, including **Extend in Video**, **Use as Reference Video** and **Use as Conditioning Clip**. With several items selected, the menu offers the actions that apply to all of them, such as **Star All**, **Download Selection**, **Change Board** and **Delete Selection**; for several images it also leads with **Add to Current Canvas** and **New Project from Images**.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,29 @@ This operation changes where image files and thumbnails are stored on disk. It d

## Access

Image storage maintenance is available from the in-application Settings panel.
Open **Settings → Server → Image storage**. The **Folder layout for new images** select changes `image_subfolder_strategy` immediately for images saved from then on. Below it, **Move existing images** shows how many images are stored outside the current layout, the state of the last move job, and the **Start Move** and **Recover** buttons; each asks for confirmation before it starts.

Administrators can start image moves, force recovery, and inspect the current move status. If multi-user mode is disabled, the single local user has the same access. Non-admin users in multi-user mode cannot run or inspect image move status.
- **Start Move** is available when images are stored outside the current layout and no interrupted job is waiting for recovery. The server still refuses it while any queue item is pending or in progress.
- **Recover** is available only when a move was interrupted and still needs finishing.
- Both buttons are unavailable while a job runs or a layout change is being saved. The status line or a note below the buttons says why a button is unavailable.

While a job runs and the Image storage setting is open, the status refreshes every few seconds and the folder layout cannot be changed. Closing Settings stops the refresh; reopen it to see the current state.

Administrators can start image moves, force recovery, and inspect the current move status. If multi-user mode is disabled, the single local user has the same access. Non-admin users in multi-user mode do not see the Server section and cannot run or inspect image move status.

## Maintenance Mode

Image moves run as a maintenance operation. Before a move starts, InvokeAI checks that no queue work is active. While the move is running, InvokeAI prevents image reads, uploads, deletes, generation jobs, and gallery mutations from racing with the filesystem move.
Image moves run as a maintenance operation. Before a move starts, InvokeAI checks that no queue work is active. While the move is running, or an interrupted move is waiting for recovery, InvokeAI prevents image reads, uploads, deletes, generation jobs, and gallery mutations from racing with the filesystem move.

The UI shows the move or recovery state until the job is complete or requires manual attention. Gallery images and thumbnails may be unavailable while maintenance is active.
The UI shows the move or recovery state until the job is complete or requires manual attention. Gallery images and thumbnails may be unavailable while maintenance is active; an open gallery keeps checking periodically while its tab is visible and reloads them on its own shortly after maintenance ends, so you do not need to refresh the page.

## Crash Recovery

The move process is crash-recoverable. InvokeAI records each move job in its database before moving files, moves full-size images and thumbnails on disk, and updates `images.image_subfolder` only after the filesystem move succeeds.

If InvokeAI stops during a move, recovery resumes incomplete jobs. If recovery finds an ambiguous filesystem state, such as both the old and new full-size image files existing or neither file existing, it halts that item for manual repair instead of blindly updating the database. Other items in the same job are still finalized, and the maintenance lock is released when the job is recorded as failed.

Recovery finalizes jobs that were already recorded before the stop. Images that had not yet been planned into a move job are not moved by recovery itself. The Settings panel reports how many images still need moving; run **Start Move** again to continue.
Recovery finalizes jobs that were already recorded before the stop. Images that had not yet been planned into a move job are not moved by recovery itself. The Image storage setting reports how many images still need moving; run **Start Move** again to continue. While a job is interrupted, **Start Move** stays unavailable and the status asks you to run **Recover** first.

Missing intermediate image files are treated as already cleaned up and do not halt the move. Missing non-intermediate image files, unreadable images, and truncated images are recorded as failed items. When the full-size file is still at its original path, recovery leaves it there so it can be repaired or removed safely. If a previous filesystem move already placed the full-size file at its destination, recovery keeps that destination and reconciles the database before recording the item as failed. After recovery releases the lock, back up the failed file and either replace it with a valid image or delete its image record from the gallery, then run **Start Move** again if images still need moving. Do not delete an active journal row or edit `images.image_subfolder` while maintenance is active.

Expand Down
2 changes: 1 addition & 1 deletion docs/src/content/docs/configuration/01.invokeai-yaml.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ Background indexing of new images already waits until no generation is running,

#### Image Subfolder Strategy

By default, generated images are stored in a single flat directory under `outputs/images/`. The `image_subfolder_strategy` setting lets you organize newly-created images into subfolders automatically. You can edit this setting in `invokeai.yaml` or, as an admin user, in the Settings panel.
By default, generated images are stored in a single flat directory under `outputs/images/`. The `image_subfolder_strategy` setting lets you organize newly-created images into subfolders automatically. You can edit this setting in `invokeai.yaml` or, as an admin user, under **Settings → Server → Image storage**.

```yaml
image_subfolder_strategy: flat # default value
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,8 @@
"source:src/features/fonts/launchpad.tsx",
"source:src/features/fonts/react.tsx",
"source:src/features/fonts/runtime.ts",
"source:src/features/gallery/data/imageRecovery.ts",
"source:src/features/gallery/ui/useGalleryImageRecovery.ts",
"source:src/features/identity/capabilities.ts",
"source:src/features/identity/core/schemas.ts",
"source:src/features/identity/core/sessionPolicy.ts",
Expand Down Expand Up @@ -515,6 +517,7 @@
"source:src/features/gallery/core/settings.ts",
"source:src/features/gallery/core/videoPaths.ts",
"source:src/features/gallery/data/backend.ts",
"source:src/features/gallery/data/imageRecovery.ts",
"source:src/features/gallery/data/imageUrls.ts",
"source:src/features/gallery/data/queries.ts",
"source:src/features/gallery/data/queryCache.ts",
Expand Down Expand Up @@ -543,6 +546,7 @@
"source:src/features/gallery/ui/galleryStateView.ts",
"source:src/features/gallery/ui/picker/GalleryPickerPopover.tsx",
"source:src/features/gallery/ui/useGalleryData.ts",
"source:src/features/gallery/ui/useGalleryImageRecovery.ts",
"source:src/features/gallery/ui/useGalleryUploadAction.ts",
"source:src/features/gallery/ui/useGalleryUploadInput.ts",
"source:src/features/gallery/utility.ts",
Expand Down
11 changes: 11 additions & 0 deletions invokeai/frontend/webv2/performance/browser-baseline.json
Original file line number Diff line number Diff line change
Expand Up @@ -521,13 +521,15 @@
"source:src/features/gallery/core/settings.ts",
"source:src/features/gallery/core/videoPaths.ts",
"source:src/features/gallery/data/backend.ts",
"source:src/features/gallery/data/imageRecovery.ts",
"source:src/features/gallery/data/imageUrls.ts",
"source:src/features/gallery/data/videoUrls.ts",
"source:src/features/gallery/launchpad.ts",
"source:src/features/gallery/react.ts",
"source:src/features/gallery/ui/GalleryUiContext.tsx",
"source:src/features/gallery/ui/galleryStateView.ts",
"source:src/features/gallery/ui/launchpad/RecentOutputs.tsx",
"source:src/features/gallery/ui/useGalleryImageRecovery.ts",
"source:src/features/identity/capabilities.ts",
"source:src/features/identity/core/schemas.ts",
"source:src/features/identity/core/sessionPolicy.ts",
Expand Down Expand Up @@ -912,6 +914,7 @@
"source:src/features/gallery/core/settings.ts",
"source:src/features/gallery/core/videoPaths.ts",
"source:src/features/gallery/data/backend.ts",
"source:src/features/gallery/data/imageRecovery.ts",
"source:src/features/gallery/data/imageUrls.ts",
"source:src/features/gallery/data/queries.ts",
"source:src/features/gallery/data/queryCache.ts",
Expand Down Expand Up @@ -968,6 +971,7 @@
"source:src/features/gallery/ui/useGalleryData.ts",
"source:src/features/gallery/ui/useGalleryGridHotkeys.ts",
"source:src/features/gallery/ui/useGalleryGridSelection.ts",
"source:src/features/gallery/ui/useGalleryImageRecovery.ts",
"source:src/features/gallery/ui/useGalleryStarredStrip.ts",
"source:src/features/gallery/ui/useGalleryUploadAction.ts",
"source:src/features/gallery/ui/useGalleryUploadInput.ts",
Expand Down Expand Up @@ -1605,6 +1609,7 @@
"source:src/workbench/image-actions/imageRecall.ts",
"source:src/workbench/image-actions/index.ts",
"source:src/workbench/image-actions/mediaUsage.ts",
"source:src/workbench/image-actions/pbrMapsGraph.ts",
"source:src/workbench/image-actions/recallParametersBridge.ts",
"source:src/workbench/image-actions/useDeletionConfirmation.tsx",
"source:src/workbench/image-actions/useFindGalleryItem.ts",
Expand Down Expand Up @@ -2022,6 +2027,7 @@
"source:src/features/gallery/core/settings.ts",
"source:src/features/gallery/core/videoPaths.ts",
"source:src/features/gallery/data/backend.ts",
"source:src/features/gallery/data/imageRecovery.ts",
"source:src/features/gallery/data/imageUrls.ts",
"source:src/features/gallery/data/queries.ts",
"source:src/features/gallery/data/queryCache.ts",
Expand Down Expand Up @@ -2078,6 +2084,7 @@
"source:src/features/gallery/ui/useGalleryData.ts",
"source:src/features/gallery/ui/useGalleryGridHotkeys.ts",
"source:src/features/gallery/ui/useGalleryGridSelection.ts",
"source:src/features/gallery/ui/useGalleryImageRecovery.ts",
"source:src/features/gallery/ui/useGalleryStarredStrip.ts",
"source:src/features/gallery/ui/useGalleryUploadAction.ts",
"source:src/features/gallery/ui/useGalleryUploadInput.ts",
Expand Down Expand Up @@ -2733,6 +2740,7 @@
"source:src/workbench/image-actions/imageRecall.ts",
"source:src/workbench/image-actions/index.ts",
"source:src/workbench/image-actions/mediaUsage.ts",
"source:src/workbench/image-actions/pbrMapsGraph.ts",
"source:src/workbench/image-actions/recallParametersBridge.ts",
"source:src/workbench/image-actions/useDeletionConfirmation.tsx",
"source:src/workbench/image-actions/useFindGalleryItem.ts",
Expand Down Expand Up @@ -3316,6 +3324,7 @@
"source:src/features/gallery/core/settings.ts",
"source:src/features/gallery/core/videoPaths.ts",
"source:src/features/gallery/data/backend.ts",
"source:src/features/gallery/data/imageRecovery.ts",
"source:src/features/gallery/data/imageUrls.ts",
"source:src/features/gallery/data/queries.ts",
"source:src/features/gallery/data/queryCache.ts",
Expand Down Expand Up @@ -3372,6 +3381,7 @@
"source:src/features/gallery/ui/useGalleryData.ts",
"source:src/features/gallery/ui/useGalleryGridHotkeys.ts",
"source:src/features/gallery/ui/useGalleryGridSelection.ts",
"source:src/features/gallery/ui/useGalleryImageRecovery.ts",
"source:src/features/gallery/ui/useGalleryStarredStrip.ts",
"source:src/features/gallery/ui/useGalleryUploadAction.ts",
"source:src/features/gallery/ui/useGalleryUploadInput.ts",
Expand Down Expand Up @@ -4086,6 +4096,7 @@
"source:src/workbench/image-actions/imageRecall.ts",
"source:src/workbench/image-actions/index.ts",
"source:src/workbench/image-actions/mediaUsage.ts",
"source:src/workbench/image-actions/pbrMapsGraph.ts",
"source:src/workbench/image-actions/recallParametersBridge.ts",
"source:src/workbench/image-actions/useDeletionConfirmation.tsx",
"source:src/workbench/image-actions/useFindGalleryItem.ts",
Expand Down
60 changes: 60 additions & 0 deletions invokeai/frontend/webv2/public/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -2063,6 +2063,50 @@
"failed": "Database VACUUM failed.",
"requestFailed": "The database could not be vacuumed."
},
"imageStorage": {
"adminOnly": "Only an administrator can change where images are stored.",
"layoutLabel": "Folder layout for new images",
"layoutHelp": "Applies to images saved from now on. Existing images stay where they are until you run Start Move.",
"layoutLoadFailed": "The storage layout could not be loaded.",
"layoutSaveFailed": "The storage layout could not be saved.",
"layouts": {
"flat": "Flat (one folder)",
"date": "By date (YYYY/MM/DD)",
"type": "By image category",
"hash": "By name prefix (hashed)",
"unknown": "Unknown layout ({{layout}})"
},
"maintenanceHeading": "Move existing images",
"maintenanceDescription": "Moves every image and thumbnail into the current layout. Names, boards and metadata are unchanged. While the move runs, the gallery and the queue are paused.",
"statusLoadFailed": "The image move status could not be loaded.",
"statusIdle_zero": "All images are stored in the current layout.",
"statusIdle_one": "{{count}} image is stored outside the current layout.",
"statusIdle_other": "{{count}} images are stored outside the current layout.",
"statusMoving": "Moving images into the current layout…",
"statusRecovering": "Recovering an interrupted image move…",
"statusNeedsRecovery": "An image move was interrupted. Run Recover to finish it before starting another move.",
"latestJob": "Last move: {{state}}",
"jobStates": {
"planned": "planned",
"moving": "moving",
"moved": "moved",
"committed": "completed",
"error": "failed"
},
"startMove": "Start Move",
"startConfirmTitle": "Move all images into the current layout?",
"startConfirmBody": "InvokeAI pauses image reads, uploads, deletions and generation for everyone on this server until the move finishes. It cannot start while queue work is active.",
"startFailed": "The image move could not be started.",
"recover": "Recover",
"recoverConfirmTitle": "Recover the image move journal?",
"recoverConfirmBody": "Recovery finishes moves that were recorded before the server stopped. Items in an ambiguous state are left for manual repair and reported here.",
"recoverFailed": "Image move recovery could not be started.",
"unavailableStatus": "Start Move and Recover become available once the move status has loaded.",
"unavailableRunning": "Start Move and Recover become available again when the current job finishes.",
"unavailableSavingLayout": "Start Move and Recover become available once the new layout is saved.",
"recoverNotNeeded": "Recover is only needed after a move is interrupted.",
"nothingToDo": "Nothing to move, and no interrupted move to recover."
},
"galleryMaintenance": {
"heading": "Gallery maintenance",
"removeMissing": "Remove records for missing images",
Expand Down Expand Up @@ -2203,6 +2247,10 @@
"label": "Generation devices",
"description": "Server-wide accelerator selection. Changes require a server restart."
},
"imageStorage": {
"label": "Image storage",
"description": "Where this server stores image files on disk, and the maintenance job that moves existing images into that layout."
},
"maxQueueHistory": {
"label": "Queue history",
"description": "How many finished queue items the server keeps on startup. Changes require a server restart."
Expand Down Expand Up @@ -4846,6 +4894,18 @@
"missing": "This image has no workflow embedded.",
"missingVideo": "This video has no workflow embedded."
},
"pbrMaps": {
"canceled": "PBR maps canceled",
"canceledMessage": "The queue item generating maps for {{name}} was canceled.",
"completed": "PBR maps are ready",
"completedMessage": "Normal, roughness and displacement maps for {{name}} were added to the gallery.",
"failed": "Could not generate PBR maps",
"label": "Generate PBR Maps",
"queued": "Generating PBR maps",
"queuedMessage": "Normal, roughness and displacement maps for {{name}} are queued.",
"removed": "PBR maps removed from the queue",
"removedMessage": "The queue item generating maps for {{name}} was removed from the queue."
},
"delete": {
"failure_one": "Could not delete {{count}} item.",
"failure_other": "Could not delete {{count}} items.",
Expand Down
Loading
Loading