{"record":{"id":"667035ae99193835","repo":"invoke-ai/InvokeAI","slug":"not-authorized-to-move-this-image","errorCode":null,"errorMessage":"Not authorized to move this image","messagePattern":"Not authorized to move this image","errorType":"http","errorClass":"HTTPException","httpStatus":403,"severity":"error","filePath":"invokeai/app/api/routers/board_images.py","lineNumber":135,"sourceCode":"        return _ScopedRemoveOutcome.GONE\n    return _ScopedRemoveOutcome.REMOVED\n\n\ndef _assert_image_direct_owner(image_name: str, current_user: CurrentUserOrDefault) -> None:\n    \"\"\"Raise 403 if the current user is not the direct owner of the image.\n\n    This is intentionally stricter than _assert_image_owner in images.py:\n    board ownership is NOT sufficient here.  Allowing a user to add someone\n    else's image to their own board would grant them mutation rights via the\n    board-ownership fallback in _assert_image_owner, escalating read access\n    into write access.\n    \"\"\"\n    if current_user.is_admin:\n        return\n    owner = ApiDependencies.invoker.services.image_records.get_user_id(image_name)\n    if owner is not None and owner == current_user.user_id:\n        return\n    raise HTTPException(status_code=403, detail=\"Not authorized to move this image\")\n\n\n@board_images_router.post(\n    \"/\",\n    operation_id=\"add_image_to_board\",\n    responses={\n        201: {\"description\": \"The image was added to a board successfully\"},\n    },\n    status_code=201,\n    response_model=AddImagesToBoardResult,\n)\ndef add_image_to_board(\n    current_user: CurrentUserOrDefault,\n    board_id: str = Body(description=\"The id of the board to add to\"),\n    image_name: str = Body(description=\"The name of the image to add\"),\n) -> AddImagesToBoardResult:\n    \"\"\"Creates a board_image\"\"\"\n    _assert_board_write_access(board_id, current_user)","sourceCodeStart":117,"sourceCodeEnd":153,"githubUrl":"https://github.com/invoke-ai/InvokeAI/blob/0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06/invokeai/app/api/routers/board_images.py#L117-L153","documentation":"_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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Only move images you generated/own, or have an admin perform the move","Verify the image_name is correct and belongs to the current user before batching","If the owner is legitimately you but resolution fails, check the image record store for consistency"],"exampleFix":"// before\nawait api.addImagesToBoard({ board_id, image_names: [...mine, ...theirs] }); // 403\n// after\nconst mine = imageNames.filter(n => owners[n] === currentUser.user_id);\nawait api.addImagesToBoard({ board_id, image_names: mine });","handlingStrategy":"validation","validationCode":"const owner = await api.getImageOwner(imageName); // or maintain a local ownership map\nif (!currentUser.is_admin && owner !== currentUser.user_id) {\n  throw new Error(`Not authorized to move image ${imageName}`);\n}\nawait api.addImageToBoard({ board_id: boardId, image_name });","typeGuard":"function canMoveImage(ownerId: string | null, user: { user_id: string; is_admin: boolean }): boolean {\n  return user.is_admin || (ownerId !== null && ownerId === user.user_id);\n}","tryCatchPattern":"try {\n  await api.addImagesToBoard({ board_id: boardId, image_names });\n} catch (e) {\n  if (e.response?.status === 403 && e.response?.data?.detail === 'Not authorized to move this image') {\n    filterToOwnedImagesAndRetry();\n  } else throw e;\n}","preventionTips":["Filter batch moves to images owned by the current user","Never move other users' images; ask an admin instead","Verify image names resolve to existing records you own before batching"],"tags":["http-403","authorization","image","board"],"backgroundTag":"insufficient-permissions","analyzedSha":"0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06","analyzedAt":"2026-08-29T04:46:49.967Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}