invoke-ai/InvokeAI · error · HTTPException

Not authorized to move this image

Error message

Not authorized to move this image

What it means

_assert_image_direct_owner raises 403 'Not authorized to move this image' when the caller is not an admin and is not the recorded owner of the image (image_records.get_user_id(image_name) returns None or a different user). It is enforced by add_image_to_board and add_images_to_board before moving images into a board.

Source

Thrown at invokeai/app/api/routers/board_images.py:135

        return _ScopedRemoveOutcome.GONE
    return _ScopedRemoveOutcome.REMOVED


def _assert_image_direct_owner(image_name: str, current_user: CurrentUserOrDefault) -> None:
    """Raise 403 if the current user is not the direct owner of the image.

    This is intentionally stricter than _assert_image_owner in images.py:
    board ownership is NOT sufficient here.  Allowing a user to add someone
    else's image to their own board would grant them mutation rights via the
    board-ownership fallback in _assert_image_owner, escalating read access
    into write access.
    """
    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
    raise HTTPException(status_code=403, detail="Not authorized to move this image")


@board_images_router.post(
    "/",
    operation_id="add_image_to_board",
    responses={
        201: {"description": "The image was added to a board successfully"},
    },
    status_code=201,
    response_model=AddImagesToBoardResult,
)
def add_image_to_board(
    current_user: CurrentUserOrDefault,
    board_id: str = Body(description="The id of the board to add to"),
    image_name: str = Body(description="The name of the image to add"),
) -> AddImagesToBoardResult:
    """Creates a board_image"""
    _assert_board_write_access(board_id, current_user)

View on GitHub (pinned to 0b6a024f2f)

Solutions

  1. Only move images you generated/own, or have an admin perform the move
  2. Verify the image_name is correct and belongs to the current user before batching
  3. If the owner is legitimately you but resolution fails, check the image record store for consistency

Example fix

// before
await api.addImagesToBoard({ board_id, image_names: [...mine, ...theirs] }); // 403
// after
const mine = imageNames.filter(n => owners[n] === currentUser.user_id);
await api.addImagesToBoard({ board_id, image_names: mine });
Defensive patterns

Strategy: validation

Validate before calling

const owner = await api.getImageOwner(imageName); // or maintain a local ownership map
if (!currentUser.is_admin && owner !== currentUser.user_id) {
  throw new Error(`Not authorized to move image ${imageName}`);
}
await api.addImageToBoard({ board_id: boardId, image_name });

Type guard

function canMoveImage(ownerId: string | null, user: { user_id: string; is_admin: boolean }): boolean {
  return user.is_admin || (ownerId !== null && ownerId === user.user_id);
}

Try / catch

try {
  await api.addImagesToBoard({ board_id: boardId, image_names });
} catch (e) {
  if (e.response?.status === 403 && e.response?.data?.detail === 'Not authorized to move this image') {
    filterToOwnedImagesAndRetry();
  } else throw e;
}

Prevention

When it happens

Trigger: POST board-image add calls (single or batch) where the image_name belongs to another user, or the image record no longer resolves to an owner (owner is None).

Common situations: On shared instances, users trying to file another user's generated image into their own board; batch moves that include images from multiple owners; deleted images whose records return None owner.

Related errors


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