invoke-ai/InvokeAI · error · HTTPException

Not authorized to modify this board

Error message

Not authorized to modify this board

What it means

_assert_board_write_access raises 403 'Not authorized to modify this board' when the caller is not an admin, does not own the board (board.user_id != current_user.user_id), and the board's visibility is not Public. Only admins, the owner, or Public-visibility boards pass the check.

Source

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

    event loop — but a 1000-name batch still holds one for six thousand round trips.)
    """
    from invokeai.app.services.board_records.board_records_common import BoardVisibility

    try:
        board = ApiDependencies.invoker.services.board_records.get(board_id)
    except BoardRecordNotFoundException:
        raise HTTPException(status_code=404, detail="Board not found")
    # Anything else — a locked or unreadable database — propagates. Catching it here would
    # answer "no such board", which the batch loops below treat as a name to skip: a disk error
    # would then drop names out of the response entirely, reported neither as moved nor as
    # failed, and the client would show the move as done until the next refresh.
    if current_user.is_admin:
        return
    if board.user_id == current_user.user_id:
        return
    if board.board_visibility == BoardVisibility.Public:
        return
    raise HTTPException(status_code=403, detail="Not authorized to modify this board")


def _image_record_exists(image_name: str) -> bool:
    """True if the image record is still present, False if it has been deleted.

    A storage error answers True: only a record positively known to be gone may be downgraded
    from a reported failure to a silent skip. `ImageRecordStorage.get` no longer translates
    sqlite errors into not-found, so the two cases are distinguishable here.
    """
    try:
        ApiDependencies.invoker.services.image_records.get(image_name)
        return True
    except ImageRecordNotFoundException:
        return False
    except Exception:
        return True

View on GitHub (pinned to 0b6a024f2f)

Solutions

  1. Have the board owner change board_visibility to Public (or perform the mutation as the owner)
  2. Perform the operation with an admin account
  3. Request ownership transfer or use your own board instead of the other user's

Example fix

// before
await api.addImageToBoard({ board_id: otherUsersBoardId, image_name }); // 403
// after
if (currentUser.is_admin || board.user_id === currentUser.user_id || board.board_visibility === 'Public') {
  await api.addImageToBoard({ board_id: board.board_id, image_name });
}
Defensive patterns

Strategy: validation

Validate before calling

const board = await api.getBoard(boardId);
const mayModify = currentUser.is_admin || board.user_id === currentUser.user_id || board.board_visibility === 'Public';
if (!mayModify) throw new Error('Not authorized to modify this board');
await api.addImageToBoard({ board_id: boardId, image_name });

Type guard

function canModifyBoard(board: BoardDTO, user: { user_id: string; is_admin: boolean }): boolean {
  return user.is_admin || board.user_id === user.user_id || board.board_visibility === 'Public';
}

Try / catch

try {
  await api.addImageToBoard({ board_id: boardId, image_name });
} catch (e) {
  if (e.response?.status === 403 && e.response?.data?.detail === 'Not authorized to modify this board') {
    notifyNeedsOwnershipOrAdmin();
  } else throw e;
}

Prevention

When it happens

Trigger: Any board image add/remove call where the authenticated user is neither the board owner nor an admin, and board.board_visibility is Private or something other than Public.

Common situations: Shared InvokeAI instance where users reference each other's boards by id; a board whose visibility was changed back to Private after the client cached access; non-admin service accounts touching other users' boards.

Related errors


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