{"record":{"id":"5efdcd9f0ec09da3","repo":"invoke-ai/InvokeAI","slug":"not-authorized-to-modify-this-board","errorCode":null,"errorMessage":"Not authorized to modify this board","messagePattern":"Not authorized to modify this board","errorType":"http","errorClass":"HTTPException","httpStatus":403,"severity":"error","filePath":"invokeai/app/api/routers/board_images.py","lineNumber":50,"sourceCode":"    event loop — but a 1000-name batch still holds one for six thousand round trips.)\n    \"\"\"\n    from invokeai.app.services.board_records.board_records_common import BoardVisibility\n\n    try:\n        board = ApiDependencies.invoker.services.board_records.get(board_id)\n    except BoardRecordNotFoundException:\n        raise HTTPException(status_code=404, detail=\"Board not found\")\n    # Anything else — a locked or unreadable database — propagates. Catching it here would\n    # answer \"no such board\", which the batch loops below treat as a name to skip: a disk error\n    # would then drop names out of the response entirely, reported neither as moved nor as\n    # failed, and the client would show the move as done until the next refresh.\n    if current_user.is_admin:\n        return\n    if board.user_id == current_user.user_id:\n        return\n    if board.board_visibility == BoardVisibility.Public:\n        return\n    raise HTTPException(status_code=403, detail=\"Not authorized to modify this board\")\n\n\ndef _image_record_exists(image_name: str) -> bool:\n    \"\"\"True if the image record is still present, False if it has been deleted.\n\n    A storage error answers True: only a record positively known to be gone may be downgraded\n    from a reported failure to a silent skip. `ImageRecordStorage.get` no longer translates\n    sqlite errors into not-found, so the two cases are distinguishable here.\n    \"\"\"\n    try:\n        ApiDependencies.invoker.services.image_records.get(image_name)\n        return True\n    except ImageRecordNotFoundException:\n        return False\n    except Exception:\n        return True\n\n","sourceCodeStart":32,"sourceCodeEnd":68,"githubUrl":"https://github.com/invoke-ai/InvokeAI/blob/0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06/invokeai/app/api/routers/board_images.py#L32-L68","documentation":"_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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Have the board owner change board_visibility to Public (or perform the mutation as the owner)","Perform the operation with an admin account","Request ownership transfer or use your own board instead of the other user's"],"exampleFix":"// before\nawait api.addImageToBoard({ board_id: otherUsersBoardId, image_name }); // 403\n// after\nif (currentUser.is_admin || board.user_id === currentUser.user_id || board.board_visibility === 'Public') {\n  await api.addImageToBoard({ board_id: board.board_id, image_name });\n}","handlingStrategy":"validation","validationCode":"const board = await api.getBoard(boardId);\nconst mayModify = currentUser.is_admin || board.user_id === currentUser.user_id || board.board_visibility === 'Public';\nif (!mayModify) throw new Error('Not authorized to modify this board');\nawait api.addImageToBoard({ board_id: boardId, image_name });","typeGuard":"function canModifyBoard(board: BoardDTO, user: { user_id: string; is_admin: boolean }): boolean {\n  return user.is_admin || board.user_id === user.user_id || board.board_visibility === 'Public';\n}","tryCatchPattern":"try {\n  await api.addImageToBoard({ board_id: boardId, image_name });\n} catch (e) {\n  if (e.response?.status === 403 && e.response?.data?.detail === 'Not authorized to modify this board') {\n    notifyNeedsOwnershipOrAdmin();\n  } else throw e;\n}","preventionTips":["Check ownership/visibility client-side before issuing board mutations","Use admin credentials for cross-user board operations","Re-check board visibility after any sharing/permission changes"],"tags":["http-403","authorization","board","permissions"],"backgroundTag":"insufficient-permissions","analyzedSha":"0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06","analyzedAt":"2026-08-29T04:46:49.967Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}