invoke-ai/InvokeAI · error · HTTPException
Image not found
Error message
Image not found
What it means
`_assert_image_record_exists` raises this 404 when the requested image name has no row in the image_records store. It runs on the refusal path of `assert_image_read_access` so a truly deleted image returns 404 instead of 403, telling clients the reference is permanently gone.
Source
Thrown at invokeai/app/api/routers/_access.py:81
flipped back to Shared, an owner re-granting access), and dropping the reference over one
destroys work the user cannot get back by restoring the permission.
Nothing above can tell them apart: the ownership test rests on `images.user_id`, which is
gone with the row, so a deleted image reaches that same 403 as a foreign one. So the
distinction is made here, on the refusal path only — the happy path pays nothing for it.
A storage error propagates rather than answering either, so an unreadable database cannot
present as a deleted image and take the user's references down with it. `exists` is a bare
row probe rather than `get` for the same reason from the other side: `get` deserializes, so
a row written by a newer version — an enum value this one does not know — would fail exactly
as absence does, and a live image would be reported gone.
The cost is that an authenticated caller can now tell an absent image from one they may not
read. Image names are generated UUIDs, so this buys an attacker nothing they could enumerate,
and it is the answer admins have always received.
"""
if not ApiDependencies.invoker.services.image_records.exists(image_name):
raise HTTPException(status_code=404, detail="Image not found")
def assert_image_read_access(image_name: str, current_user: CurrentUserOrDefault) -> None:
"""Raise 403 if the current user may not view the image.
Access is granted when ANY of these hold:
- The user is an admin.
- The user owns the image.
- The image sits on a shared or public board.
"""
if current_user.is_admin:
return
owner = ApiDependencies.invoker.services.image_records.get_user_id(image_name)
if owner is not None and owner == current_user.user_id:
return
board_id = ApiDependencies.invoker.services.board_image_records.get_board_for_image(image_name)View on GitHub (pinned to 0b6a024f2f)
Solutions
- Drop the stale image reference and pick a different image; deletion is permanent
- Re-generate the image (re-run the workflow/queue item) to recreate a new image name
- Check the database/store points at the correct storage backend (misconfigured output/DB path can make all images look missing)
- Confirm with an admin whether the image was removed by a pruning job (max_queue_history / disk cleanup)
Example fix
// before
const url = `/v1/images/i/${imageName}/full`;
await fetch(url); // 404 if deleted
// after
if (imageDeleted(imageName)) removeLayerFromCanvas(imageName);
else await fetch(`/v1/images/i/${imageName}/full`); Defensive patterns
Strategy: try-catch
Validate before calling
// Check existence before dereferencing
const exists = await fetch(`/v1/images/i/${imageName}/metadata`, {headers: authHeaders}).then(r => r.ok); Try / catch
try {
const meta = await fetch(`/v1/images/i/${imageName}/metadata`, {headers: authHeaders}).then(r => {
if (r.status === 404) throw new NotFoundError(imageName);
if (!r.ok) throw new Error('fetch failed');
return r.json();
});
} catch (e) {
if (e instanceof NotFoundError) removeImageReference(e.name); // 404 = permanently gone
else throw e;
} Prevention
- Treat 404 on images as permanent and prune the reference from workflows/canvas
- Avoid persisting raw image names across cleanup/pruning operations without revalidation
- Revalidate image names after restores, migrations, or version upgrades
- Distinguish 404 (gone) from 403 (denied) — never delete references on 403
When it happens
Trigger: GET of image metadata/URL/full file (e.g. /v1/images/i/{image_name}) with a UUID name that no longer exists in the database — typically after the image was deleted or pruned, while the record lookup in read-access checking fails first.
Common situations: A UI or workflow holds a reference to an image that was deleted (or its queue history pruned); stale browser tabs; shared links to images removed by cleanup jobs.
Related errors
- Board not found
- Board not found
- str(e) (ValueError, relationship not found)
- Style preset not found
- System prompt not found
AI-assisted analysis of invoke-ai/InvokeAI@0b6a024f2f (2026-08-29).
Data as JSON: /api/errors/d09711da78ff163f.
Report an issue: GitHub.