invoke-ai/InvokeAI · error · HTTPException

Failed to delete images

Error message

Failed to delete images

What it means

HTTP 500 raised by POST /images/delete when the bulk deletion service call throws an unexpected (non-HTTPException) error. Successful but partial deletions are reported in the DeleteImagesResult payload instead of raising, so this error means the operation crashed outright.

Solutions

  1. Inspect server logs for the underlying exception
  2. Retry the delete with a smaller batch of image_names
  3. Verify image files and database are present and writable
  4. Restore missing files or clean orphaned DB records before retrying
Defensive patterns

Strategy: try-catch

Validate before calling

// confirm images still exist before bulk delete
const existing = await api.getImageDtos(imageNames);
if (existing.length !== imageNames.length) {
  imageNames = existing.map(i => i.image_name);
}

Try / catch

try {
  const res = await api.deleteImagesFromList(imageNames);
  // inspect res.failed_images for partial failures
} catch (e) {
  if (e instanceof ApiError && e.status === 500) {
    // retry in smaller batches; check server logs
  }
}

Prevention

When it happens

Trigger: DELETE /api/v1/images/delete when the images service raises while deleting the listed image_names — e.g. storage layer failure, database error, or corrupted image records.

Common situations: Image files on disk already removed manually so record deletion fails; sqlite DB locked by another process; deleting many images triggers a storage backend timeout.

Related errors


AI-assisted analysis of invoke-ai/InvokeAI@0b6a024f2f (2026-08-29). Data as JSON: /api/errors/0149966610c3f69f. Report an issue: GitHub.

Appendix: source

Thrown at invokeai/app/api/routers/images.py:606

                # would answer for names the caller was never entitled to touch.
                #
                # This is narrow only because image_records.get() no longer translates a
                # sqlite3.Error into this exception — see the comment there. If that
                # translation ever comes back, a locked or corrupt database would land here
                # and a whole failed batch would answer 200 with empty result lists.
            except Exception:
                # A genuine deletion failure (not an auth/404 skip) — report it so the
                # client can surface a partial-failure warning, matching the video path.
                failed_images.add(image_name)
        return DeleteImagesResult(
            deleted_images=list(deleted_images),
            failed_images=list(failed_images),
            affected_boards=list(affected_boards),
        )
    except HTTPException:
        raise
    except Exception:
        raise HTTPException(status_code=500, detail="Failed to delete images")


@images_router.delete("/uncategorized", operation_id="delete_uncategorized_images", response_model=DeleteImagesResult)
def delete_uncategorized_images(
    current_user: CurrentUserOrDefault,
) -> DeleteImagesResult:
    """Deletes all uncategorized images owned by the current user (or all if admin)"""
    assert_image_move_maintenance_inactive()

    image_names = ApiDependencies.invoker.services.board_images.get_all_board_image_names_for_board(
        board_id="none", categories=None, is_intermediate=None
    )

    try:
        deleted_images: set[str] = set()
        failed_images: set[str] = set()
        affected_boards: set[str] = set()
        for image_name in image_names:

View on GitHub (pinned to 0b6a024f2f)