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 translatesView on GitHub (pinned to 0b6a024f2f)
Solutions
- List boards (GET /boards/) and confirm the board_id exists before mutating
- Refresh the client board list and retry with a valid board id
- 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
- Refresh board lists after any board deletion on any client
- Never hardcode board uuids; resolve them by name at call time
- Treat 404 on board mutations as stale-cache and re-sync
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
- Board not found
- System prompt not found
- Image not found
- str(e) (ValueError, relationship not found)
- Style preset not found
AI-assisted analysis of invoke-ai/InvokeAI@0b6a024f2f (2026-08-29).
Data as JSON: /api/errors/6f1c97f1a5d87e03.
Report an issue: GitHub.