invoke-ai/InvokeAI · error · HTTPException

Board not found

Error message

Board not found

What it means

_assert_board_write_access looks up the board via board_records.get(board_id) and converts BoardRecordNotFoundException into HTTP 404 'Board not found'. It is shared by add_image_to_board, remove_image_from_board, add_images_to_board and remove_images_from_board, so any board mutation against a nonexistent board id fails with this error before any writes happen.

Source

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

    - The user is an admin.
    - The user owns the board.
    - The board visibility is Public (public boards accept contributions from any user).

    Reads the board *record*, not its DTO. The decision needs only the owner and the
    visibility, while BoardService.get_dto also resolves the cover image and runs three COUNT
    aggregates over the board's contents — six queries to answer a question two columns settle.
    That cost is the only reason a batch route would be tempted to decide once and reuse the
    answer for every name, and reusing it is what lets a permission revoked mid-batch keep
    working until the request ends. One indexed SELECT per name is cheap enough to re-decide.
    (These routes are sync `def`, so the queries occupy a threadpool worker rather than the
    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

View on GitHub (pinned to 0b6a024f2f)

Solutions

  1. List boards (GET /boards/) and confirm the board_id exists before mutating
  2. Refresh the client board list and retry with a valid board id
  3. If scripting, fetch the id dynamically instead of hardcoding a uuid

Example fix

// before
await api.addImageToBoard({ board_id: 'stale-id', image_name }); // 404
// after
const boards = await api.listBoards();
const board = boards.find(b => b.board_name === 'My Board');
if (board) await api.addImageToBoard({ board_id: board.board_id, image_name });
Defensive patterns

Strategy: validation

Validate before calling

const boards = await api.listBoards();
if (!boards.some(b => b.board_id === boardId)) {
  throw new Error(`Board ${boardId} does not exist`);
}
await api.addImageToBoard({ board_id: boardId, image_name });

Type guard

function boardExists(boards: BoardDTO[], boardId: string): boardId is string {
  return boards.some(b => b.board_id === boardId);
}

Try / catch

try {
  await api.addImageToBoard({ board_id: boardId, image_name });
} catch (e) {
  if (e.response?.status === 404 && e.response?.data?.detail === 'Board not found') {
    await refreshBoardList();
  } else throw e;
}

Prevention

When it happens

Trigger: POST/DELETE board image endpoints with a board_id that does not exist (deleted board, mistyped id, board on a different InvokeAI instance).

Common situations: Stale client cache holding a board that was deleted elsewhere; copied board ids between dev/prod instances; typos in board uuid when scripting against the API.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


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