{"record":{"id":"55b7927c773d4678","repo":"invoke-ai/InvokeAI","slug":"failed-to-add-images-to-board","errorCode":null,"errorMessage":"Failed to add images to board","messagePattern":"Failed to add images to board","errorType":"http","errorClass":"HTTPException","httpStatus":500,"severity":"error","filePath":"invokeai/app/api/routers/board_images.py","lineNumber":324,"sourceCode":"                # reverted on reload.\n                #\n                # Except that a name deleted between the ownership check and the insert lands\n                # here too, and not as something recognizable: board_images.image_name is a\n                # foreign key onto images.image_name, so the INSERT fails with a bare\n                # sqlite3.IntegrityError. Nothing in the exception says \"gone\", so the record\n                # is probed instead — only on this path, so the happy path pays nothing.\n                if not _image_record_exists(image_name):\n                    continue\n                failed_images.add(image_name)\n        return AddImagesToBoardResult(\n            added_images=list(added_images),\n            failed_images=list(failed_images),\n            affected_boards=list(affected_boards),\n        )\n    except HTTPException:\n        raise\n    except Exception:\n        raise HTTPException(status_code=500, detail=\"Failed to add images to board\")\n\n\n@board_images_router.post(\n    \"/batch/delete\",\n    operation_id=\"remove_images_from_board\",\n    responses={\n        201: {\"description\": \"Images were removed from board successfully\"},\n    },\n    status_code=201,\n    response_model=RemoveImagesFromBoardResult,\n)\ndef remove_images_from_board(\n    current_user: CurrentUserOrDefault,\n    image_names: list[ImageName] = Body(\n        description=\"The names of the images to remove\", embed=True, max_length=MAX_IMAGE_BATCH_SIZE\n    ),\n) -> RemoveImagesFromBoardResult:\n    \"\"\"Removes a list of images from their board, if they had one\"\"\"","sourceCodeStart":306,"sourceCodeEnd":342,"githubUrl":"https://github.com/invoke-ai/InvokeAI/blob/0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06/invokeai/app/api/routers/board_images.py#L306-L342","documentation":"HTTP 500 raised by POST /board_images/batch (add_images_to_board) when the bulk add flow throws any exception that is not an HTTPException. Unlike per-image HTTP errors which are collected in failed_images, unexpected service/DB failures bubble up as this generic 500.","triggerScenarios":"POST /board_images/batch with body {image_names: [...], board_id} where the boards service throws while adding associations — e.g. board_id deleted concurrently, database error, or a service-layer exception.","commonSituations":"Board deleted by another client between UI load and batch add, Postgres/SQLite connection drop, invalid board_id containing characters that break the lookup, or invoking the batch while the DB is under migration.","solutions":["Inspect server logs for the original exception trace","Validate board_id exists first via GET /boards/{board_id}","Re-run the batch for only the images missing from failed_images","Check database connectivity and disk space","Update InvokeAI if hits persist on a current board_id"],"exampleFix":"// before\nawait api.post('/board_images/batch', { image_names, board_id });\n// after\nconst board = await api.get(`/boards/${board_id}`); // 404 early if board gone\nawait api.post('/board_images/batch', { image_names, board_id });","handlingStrategy":"validation","validationCode":"const board = await api.get(`/boards/${boardId}`).catch(() => null);\nif (!board) throw new Error(`Board ${boardId} not found; aborting batch add`);","typeGuard":"const isBoardMissing = (e) => e?.response?.status === 404;","tryCatchPattern":"try {\n  await api.post('/board_images/batch', { image_names, board_id });\n} catch (e) {\n  if (e.response?.status === 500) {\n    // retry per-image to isolate failures\n    await Promise.allSettled(image_names.map(n => api.post('/board_images/', { image_name: n, board_id })));\n    return;\n  }\n  throw e;\n}","preventionTips":["Validate board_id against GET /boards/ before batch operations","Use failed_images from partial responses to guide retries","Avoid concurrent batch mutations of the same board","Keep DB (SQLite/Postgres) reachable and monitor locks"],"tags":["http-500","api","batch","database"],"backgroundTag":"unexpected-internal-server-error","analyzedSha":"0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06","analyzedAt":"2026-08-29T04:46:49.967Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}