{"record":{"id":"c426d784ec8e0151","repo":"invoke-ai/InvokeAI","slug":"failed-to-update-image","errorCode":null,"errorMessage":"Failed to update image","messagePattern":"Failed to update image","errorType":"http","errorClass":"HTTPException","httpStatus":400,"severity":"error","filePath":"invokeai/app/api/routers/images.py","lineNumber":303,"sourceCode":"\n@images_router.patch(\n    \"/i/{image_name}\",\n    operation_id=\"update_image\",\n    response_model=ImageDTO,\n)\ndef update_image(\n    current_user: CurrentUserOrDefault,\n    image_name: str = Path(description=\"The name of the image to update\"),\n    image_changes: ImageRecordChanges = Body(description=\"The changes to apply to the image\"),\n) -> ImageDTO:\n    \"\"\"Updates an image\"\"\"\n    _assert_image_owner(image_name, current_user)\n    assert_image_move_maintenance_inactive()\n\n    try:\n        return ApiDependencies.invoker.services.images.update(image_name, image_changes)\n    except Exception:\n        raise HTTPException(status_code=400, detail=\"Failed to update image\")\n\n\n@images_router.get(\n    \"/i/{image_name}\",\n    operation_id=\"get_image_dto\",\n    response_model=ImageDTO,\n)\ndef get_image_dto(\n    current_user: CurrentUserOrDefault,\n    image_name: str = Path(description=\"The name of image to get\"),\n) -> ImageDTO:\n    \"\"\"Gets an image's DTO\"\"\"\n    _assert_image_read_access(image_name, current_user)\n\n    try:\n        return ApiDependencies.invoker.services.images.get_dto(image_name)\n    except ImageRecordNotFoundException:\n        # Only a genuinely missing record answers 404. This route is what a workflow's image","sourceCodeStart":285,"sourceCodeEnd":321,"githubUrl":"https://github.com/invoke-ai/InvokeAI/blob/0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06/invokeai/app/api/routers/images.py#L285-L321","documentation":"HTTP 400 raised by PATCH /i/{image_name} when ApiDependencies.invoker.services.images.update() throws. The endpoint first checks image ownership and image-move maintenance state, so a 400 here typically means the update itself failed (bad change shape, image not found, or metadata constraint violated).","triggerScenarios":"PATCH /api/v1/images/i/{image_name} with image_changes referencing nonexistent fields/categories, a nonexistent image_name, or a service-level write failure.","commonSituations":"Client sends stale image_name after the image was deleted; changing board/category to a board the image cannot move to; schema drift between client SDK version and server API version.","solutions":["Confirm image_name exists via GET /api/v1/images/i/{image_name} first","Validate image_changes against the current ImageRecordChanges schema","Check the image is not in a board under image-move maintenance","Retry after refreshing the image list if the name was stale"],"exampleFix":"// before\nawait api.patch(`/images/i/${name}`, { changes: { starred: 'yes' } });\n// after\nawait api.patch(`/images/i/${name}`, { changes: { starred: true } });","handlingStrategy":"validation","validationCode":"// fetch the image first and validate the change shape\nconst dto = await api.getImageDto(name); // throws 404 if missing\nif (typeof changes.starred !== 'boolean') throw new Error('starred must be boolean');","typeGuard":null,"tryCatchPattern":"try {\n  await api.updateImage(name, changes);\n} catch (e) {\n  if (e instanceof ApiError && e.status === 400) {\n    // refresh image existence and change schema, then retry once\n  }\n}","preventionTips":["Always GET the image DTO before PATCHing to confirm it exists","Keep the client SDK in sync with the server API version","Validate ImageRecordChanges fields against the current schema","Handle 'image moved to maintenance' states before updating"],"tags":["http-400","api","invokeai"],"backgroundTag":"image-update-failed","analyzedSha":"0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06","analyzedAt":"2026-08-29T04:46:49.967Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}