[GH-ISSUE #24565] issue: edit_image with ComfyUI no longer returns images in 0.9.5 #74940

Open
opened 2026-05-13 07:48:35 -05:00 by GiteaMirror · 9 comments
Owner

Originally created by @seamon67 on GitHub (May 11, 2026).
Original GitHub issue: https://github.com/open-webui/open-webui/issues/24565

Check Existing Issues

  • I have searched for any existing and/or related issues.
  • I have searched for any existing and/or related discussions.
  • I have also searched in the CLOSED issues AND CLOSED discussions and found no related items (your issue might already be addressed on the development branch!).
  • I am using the latest version of Open WebUI.

Installation Method

Docker

Open WebUI Version

0.9.5

Ollama Version (if applicable)

No response

Operating System

Linux

Browser (if applicable)

No response

Confirmation

  • I have read and followed all instructions in README.md.
  • I am using the latest version of both Open WebUI and Ollama.
  • I have included the browser console logs.
  • I have included the Docker container logs.
  • I have provided every relevant configuration, setting, and environment variable used in my setup.
  • I have clearly listed every relevant configuration, custom setting, environment variable, and command-line option that influences my setup (such as Docker Compose overrides, .env values, browser settings, authentication configurations, etc).
  • I have documented step-by-step reproduction instructions that are precise, sequential, and leave nothing to interpretation. My steps:
  • Start with the initial platform/version/OS and dependencies used,
  • Specify exact install/launch/configure commands,
  • List URLs visited, user input (incl. example values/emails/passwords if needed),
  • Describe all options and toggles enabled or changed,
  • Include any files or environmental changes,
  • Identify the expected and actual result at each stage,
  • Ensure any reasonably skilled user can follow and hit the same issue.

Expected Behavior

edit_image when used with ComfyUI should work and return an image to be displayer to the user.

Actual Behavior

  1. edit_image is successfully called.
  2. ComfyUI is successfully called and generates the image.
  3. When ComfyUI returns the image, an error is thrown in the chat
    "error": "400: [ERROR: 'NoneType' object has no attribute 'lower']"

Steps to Reproduce

  1. Make sure edit_image is configured through a ComfyUI workflow.
  2. Tell LLM to edit_image.
  3. Wait for edit_image to complete.
  4. Error is displayed in the tool call.

Logs & Screenshots

Traceback (most recent call last):

File "", line 198, in _run_module_as_main
File "", line 88, in _run_code
File "/usr/local/lib/python3.11/site-packages/uvicorn/main.py", line 4, in
uvicorn.main()
│ └
└ <module 'uvicorn' from '/usr/local/lib/python3.11/site-packages/uvicorn/init.py'>
File "/usr/local/lib/python3.11/site-packages/click/core.py", line 1514, in call
return self.main(args, **kwargs)
│ │ │ └ {}
│ │ └ ()
│ └ <function Command.main at 0x14ade80ff240>

File "/usr/local/lib/python3.11/site-packages/click/core.py", line 1435, in main
rv = self.invoke(ctx)
│ │ └ <click.core.Context object at 0x14ade8df50d0>
│ └ <function Command.invoke at 0x14ade80fef20>

File "/usr/local/lib/python3.11/site-packages/click/core.py", line 1298, in invoke
return ctx.invoke(self.callback, **ctx.params)
│ │ │ │ │ └ {'host': '0.0.0.0', 'port': 8080, 'forwarded_allow_ips': '
', 'workers': 1, 'app': 'open_webui.main:app', 'uds': None, 'fd': ...
│ │ │ │ └ <click.core.Context object at 0x14ade8df50d0>
│ │ │ └ <function main at 0x14ade7ed42c0>
│ │ └
│ └ <function Context.invoke at 0x14ade80fe160>
└ <click.core.Context object at 0x14ade8df50d0>
File "/usr/local/lib/python3.11/site-packages/click/core.py", line 853, in invoke
return callback(args, **kwargs)
│ │ └ {'host': '0.0.0.0', 'port': 8080, 'forwarded_allow_ips': '
', 'workers': 1, 'app': 'open_webui.main:app', 'uds': None, 'fd': ...
│ └ ()
└ <function main at 0x14ade7ed42c0>
File "/usr/local/lib/python3.11/site-packages/uvicorn/main.py", line 433, in main
run(
└ <function run at 0x14ade7f95ee0>
File "/usr/local/lib/python3.11/site-packages/uvicorn/main.py", line 606, in run
server.run()
│ └ <function Server.run at 0x14ade7f95760>
└ <uvicorn.server.Server object at 0x14ade8133e50>
File "/usr/local/lib/python3.11/site-packages/uvicorn/server.py", line 75, in run
return asyncio_run(self.serve(sockets=sockets), loop_factory=self.config.get_loop_factory())
│ │ │ │ │ │ └ <function Config.get_loop_factory at 0x14ade80cc400>
│ │ │ │ │ └ <uvicorn.config.Config object at 0x14ade7ed9c50>
│ │ │ │ └ <uvicorn.server.Server object at 0x14ade8133e50>
│ │ │ └ None
│ │ └ <function Server.serve at 0x14ade7f95800>
│ └ <uvicorn.server.Server object at 0x14ade8133e50>
└ <function asyncio_run at 0x14ade8102200>
File "/usr/local/lib/python3.11/site-packages/uvicorn/_compat.py", line 30, in asyncio_run
return runner.run(main)
│ │ └ <coroutine object Server.serve at 0x14ade7e3b1f0>
│ └ <function Runner.run at 0x14ade8354fe0>
└ <asyncio.runners.Runner object at 0x14ade7ee1590>
File "/usr/local/lib/python3.11/asyncio/runners.py", line 118, in run
return self._loop.run_until_complete(task)
│ │ │ └ <Task pending name='Task-1' coro=<Server.serve() running at /usr/local/lib/python3.11/site-packages/uvicorn/server.py:79> wai...
│ │ └ <cyfunction Loop.run_until_complete at 0x14ade7bfa740>
│ └ <uvloop.Loop running=True closed=False debug=False>
└ <asyncio.runners.Runner object at 0x14ade7ee1590>

File "/app/backend/open_webui/main.py", line 1997, in process_chat
return await process_chat_response(response, ctx)
│ │ └ {'request': <starlette.requests.Request object at 0x14ad71a817d0>, 'form_data': {'stream': True, 'model': 'Gemma:31b', 'strea...
│ └ <starlette.responses.StreamingResponse object at 0x14ad730893d0>
└ <function process_chat_response at 0x14ad77514360>

File "/app/backend/open_webui/utils/middleware.py", line 5204, in process_chat_response
return await streaming_chat_response_handler(response, ctx)
│ │ └ {'request': <starlette.requests.Request object at 0x14ad71a817d0>, 'form_data': {'stream': True, 'model': 'Gemma:31b', 'strea...
│ └ <starlette.responses.StreamingResponse object at 0x14ad730893d0>
└ <function streaming_chat_response_handler at 0x14ad775142c0>

File "/app/backend/open_webui/utils/middleware.py", line 5152, in streaming_chat_response_handler
return await response_handler(response, events)
│ │ └ []
│ └ <starlette.responses.StreamingResponse object at 0x14ad730893d0>
└ <function streaming_chat_response_handler..response_handler at 0x14ad095b3060>

File "/app/backend/open_webui/utils/middleware.py", line 4599, in response_handler
tool_result = await tool_function(**tool_function_params)
│ └ {'image_urls': ['/api/v1/files/c3c9da27-194e-4c1d-9c14-532d487e74d9/content'], 'prompt': 'Insert the following translated Eng...
└ <function edit_image at 0x14ad71dd5c60>

File "/app/backend/open_webui/utils/tools.py", line 136, in new_function
return await partial_func(*args, **kwargs)
│ │ └ {'image_urls': ['/api/v1/files/c3c9da27-194e-4c1d-9c14-532d487e74d9/content'], 'prompt': 'Insert the following translated Eng...
│ └ ()
└ functools.partial(<function edit_image at 0x14ad7753c5e0>, request=<starlette.requests.Request object at 0x14ad71a817d0>,...

File "/app/backend/open_webui/tools/builtin.py", line 347, in edit_image
images = await image_edits(
└ <function image_edits at 0x14ad78270220>

File "/app/backend/open_webui/routers/images.py", line 1069, in image_edits
image_data, content_type = await get_image_data(image_url, headers)
│ │ └ None
│ └ 'http://host:8188/view?filename=Flux-2-Klein+Edit_00020_.png&subfolder=&type=output'
└ <function get_image_data at 0x14ad7839f9c0>

File "/app/backend/open_webui/routers/images.py", line 446, in get_image_data
validate_url(data)
│ └ 'http://host:8188/view?filename=Flux-2-Klein+Edit_00020_.png&subfolder=&type=output'
└ <function validate_url at 0x14ad7b3e5f80>

File "/app/backend/open_webui/retrieval/web/utils.py", line 70, in validate_url
raise ValueError(ERROR_MESSAGES.INVALID_URL)
│ └ <ERROR_MESSAGES.INVALID_URL: 'Oops! The URL you provided is invalid. Please double-check and try again.'>
└ <enum 'ERROR_MESSAGES'>

ValueError: Oops! The URL you provided is invalid. Please double-check and try again.
2026-05-11 12:09:37.525 | ERROR | open_webui.tools.builtin:edit_image:388 - edit_image error: 400: [ERROR: 'NoneType' object has no attribute 'lower']
Traceback (most recent call last):

File "/app/backend/open_webui/routers/images.py", line 1070, in image_edits
_, url = await upload_image(
└ <function upload_image at 0x14ad7839fe20>

File "/app/backend/open_webui/routers/images.py", line 475, in upload_image
image_format = mimetypes.guess_extension(content_type)
│ │ └ None
│ └ <function guess_extension at 0x14ade787f420>
└ <module 'mimetypes' from '/usr/local/lib/python3.11/mimetypes.py'>

File "/usr/local/lib/python3.11/mimetypes.py", line 347, in guess_extension
return _db.guess_extension(type, strict)
│ │ │ └ True
│ │ └ None
│ └ <function MimeTypes.guess_extension at 0x14ade787f060>
└ <mimetypes.MimeTypes object at 0x14ad75ba4090>
File "/usr/local/lib/python3.11/mimetypes.py", line 202, in guess_extension
extensions = self.guess_all_extensions(type, strict)
│ │ │ └ True
│ │ └ None
│ └ <function MimeTypes.guess_all_extensions at 0x14ade787efc0>
└ <mimetypes.MimeTypes object at 0x14ad75ba4090>
File "/usr/local/lib/python3.11/mimetypes.py", line 181, in guess_all_extensions
type = type.lower()
└ None

AttributeError: 'NoneType' object has no attribute 'lower'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):

File "", line 198, in _run_module_as_main
File "", line 88, in _run_code
File "/usr/local/lib/python3.11/site-packages/uvicorn/main.py", line 4, in
uvicorn.main()
│ └
└ <module 'uvicorn' from '/usr/local/lib/python3.11/site-packages/uvicorn/init.py'>
File "/usr/local/lib/python3.11/site-packages/click/core.py", line 1514, in call
return self.main(args, **kwargs)
│ │ │ └ {}
│ │ └ ()
│ └ <function Command.main at 0x14ade80ff240>

File "/usr/local/lib/python3.11/site-packages/click/core.py", line 1435, in main
rv = self.invoke(ctx)
│ │ └ <click.core.Context object at 0x14ade8df50d0>
│ └ <function Command.invoke at 0x14ade80fef20>

File "/usr/local/lib/python3.11/site-packages/click/core.py", line 1298, in invoke
return ctx.invoke(self.callback, **ctx.params)
│ │ │ │ │ └ {'host': '0.0.0.0', 'port': 8080, 'forwarded_allow_ips': '
', 'workers': 1, 'app': 'open_webui.main:app', 'uds': None, 'fd': ...
│ │ │ │ └ <click.core.Context object at 0x14ade8df50d0>
│ │ │ └ <function main at 0x14ade7ed42c0>
│ │ └
│ └ <function Context.invoke at 0x14ade80fe160>
└ <click.core.Context object at 0x14ade8df50d0>
File "/usr/local/lib/python3.11/site-packages/click/core.py", line 853, in invoke
return callback(args, **kwargs)
│ │ └ {'host': '0.0.0.0', 'port': 8080, 'forwarded_allow_ips': '
', 'workers': 1, 'app': 'open_webui.main:app', 'uds': None, 'fd': ...
│ └ ()
└ <function main at 0x14ade7ed42c0>
File "/usr/local/lib/python3.11/site-packages/uvicorn/main.py", line 433, in main
run(
└ <function run at 0x14ade7f95ee0>
File "/usr/local/lib/python3.11/site-packages/uvicorn/main.py", line 606, in run
server.run()
│ └ <function Server.run at 0x14ade7f95760>
└ <uvicorn.server.Server object at 0x14ade8133e50>
File "/usr/local/lib/python3.11/site-packages/uvicorn/server.py", line 75, in run
return asyncio_run(self.serve(sockets=sockets), loop_factory=self.config.get_loop_factory())
│ │ │ │ │ │ └ <function Config.get_loop_factory at 0x14ade80cc400>
│ │ │ │ │ └ <uvicorn.config.Config object at 0x14ade7ed9c50>
│ │ │ │ └ <uvicorn.server.Server object at 0x14ade8133e50>
│ │ │ └ None
│ │ └ <function Server.serve at 0x14ade7f95800>
│ └ <uvicorn.server.Server object at 0x14ade8133e50>
└ <function asyncio_run at 0x14ade8102200>
File "/usr/local/lib/python3.11/site-packages/uvicorn/_compat.py", line 30, in asyncio_run
return runner.run(main)
│ │ └ <coroutine object Server.serve at 0x14ade7e3b1f0>
│ └ <function Runner.run at 0x14ade8354fe0>
└ <asyncio.runners.Runner object at 0x14ade7ee1590>
File "/usr/local/lib/python3.11/asyncio/runners.py", line 118, in run
return self._loop.run_until_complete(task)
│ │ │ └ <Task pending name='Task-1' coro=<Server.serve() running at /usr/local/lib/python3.11/site-packages/uvicorn/server.py:79> wai...
│ │ └ <cyfunction Loop.run_until_complete at 0x14ade7bfa740>
│ └ <uvloop.Loop running=True closed=False debug=False>
└ <asyncio.runners.Runner object at 0x14ade7ee1590>

File "/app/backend/open_webui/main.py", line 1997, in process_chat
return await process_chat_response(response, ctx)
│ │ └ {'request': <starlette.requests.Request object at 0x14ad71a817d0>, 'form_data': {'stream': True, 'model': 'Gemma:31b', 'strea...
│ └ <starlette.responses.StreamingResponse object at 0x14ad730893d0>
└ <function process_chat_response at 0x14ad77514360>

File "/app/backend/open_webui/utils/middleware.py", line 5204, in process_chat_response
return await streaming_chat_response_handler(response, ctx)
│ │ └ {'request': <starlette.requests.Request object at 0x14ad71a817d0>, 'form_data': {'stream': True, 'model': 'Gemma:31b', 'strea...
│ └ <starlette.responses.StreamingResponse object at 0x14ad730893d0>
└ <function streaming_chat_response_handler at 0x14ad775142c0>

File "/app/backend/open_webui/utils/middleware.py", line 5152, in streaming_chat_response_handler
return await response_handler(response, events)
│ │ └ []
│ └ <starlette.responses.StreamingResponse object at 0x14ad730893d0>
└ <function streaming_chat_response_handler..response_handler at 0x14ad095b3060>

File "/app/backend/open_webui/utils/middleware.py", line 4599, in response_handler
tool_result = await tool_function(**tool_function_params)
│ └ {'image_urls': ['/api/v1/files/c3c9da27-194e-4c1d-9c14-532d487e74d9/content'], 'prompt': 'Insert the following translated Eng...
└ <function edit_image at 0x14ad71dd5c60>

File "/app/backend/open_webui/utils/tools.py", line 136, in new_function
return await partial_func(*args, **kwargs)
│ │ └ {'image_urls': ['/api/v1/files/c3c9da27-194e-4c1d-9c14-532d487e74d9/content'], 'prompt': 'Insert the following translated Eng...
│ └ ()
└ functools.partial(<function edit_image at 0x14ad7753c5e0>, request=<starlette.requests.Request object at 0x14ad71a817d0>,...

File "/app/backend/open_webui/tools/builtin.py", line 347, in edit_image
images = await image_edits(
└ <function image_edits at 0x14ad78270220>

File "/app/backend/open_webui/routers/images.py", line 1085, in image_edits
raise HTTPException(status_code=400, detail=ERROR_MESSAGES.DEFAULT(error))
│ │ │ └ AttributeError("'NoneType' object has no attribute 'lower'")
│ │ └ <function ERROR_MESSAGES. at 0x14ade3dd89a0>
│ └ <enum 'ERROR_MESSAGES'>
└ <class 'fastapi.exceptions.HTTPException'>

fastapi.exceptions.HTTPException: 400: [ERROR: 'NoneType' object has no attribute 'lower']

Additional Information

edit_image was working perfectly in 0.9.2
I can also confirm that images are being created in ComfyUI

Originally created by @seamon67 on GitHub (May 11, 2026). Original GitHub issue: https://github.com/open-webui/open-webui/issues/24565 ### Check Existing Issues - [x] I have searched for any existing and/or related issues. - [x] I have searched for any existing and/or related discussions. - [x] I have also searched in the CLOSED issues AND CLOSED discussions and found no related items (your issue might already be addressed on the development branch!). - [x] I am using the latest version of Open WebUI. ### Installation Method Docker ### Open WebUI Version 0.9.5 ### Ollama Version (if applicable) _No response_ ### Operating System Linux ### Browser (if applicable) _No response_ ### Confirmation - [x] I have read and followed all instructions in `README.md`. - [x] I am using the latest version of **both** Open WebUI and Ollama. - [x] I have included the browser console logs. - [x] I have included the Docker container logs. - [x] I have **provided every relevant configuration, setting, and environment variable used in my setup.** - [x] I have clearly **listed every relevant configuration, custom setting, environment variable, and command-line option that influences my setup** (such as Docker Compose overrides, .env values, browser settings, authentication configurations, etc). - [x] I have documented **step-by-step reproduction instructions that are precise, sequential, and leave nothing to interpretation**. My steps: - Start with the initial platform/version/OS and dependencies used, - Specify exact install/launch/configure commands, - List URLs visited, user input (incl. example values/emails/passwords if needed), - Describe all options and toggles enabled or changed, - Include any files or environmental changes, - Identify the expected and actual result at each stage, - Ensure any reasonably skilled user can follow and hit the same issue. ### Expected Behavior edit_image when used with ComfyUI should work and return an image to be displayer to the user. ### Actual Behavior 1. edit_image is successfully called. 2. ComfyUI is successfully called and generates the image. 3. When ComfyUI returns the image, an error is thrown in the chat ``` "error": "400: [ERROR: 'NoneType' object has no attribute 'lower']" ``` ### Steps to Reproduce 1. Make sure edit_image is configured through a ComfyUI workflow. 2. Tell LLM to edit_image. 3. Wait for edit_image to complete. 4. Error is displayed in the tool call. ### Logs & Screenshots Traceback (most recent call last): File "<frozen runpy>", line 198, in _run_module_as_main File "<frozen runpy>", line 88, in _run_code File "/usr/local/lib/python3.11/site-packages/uvicorn/__main__.py", line 4, in <module> uvicorn.main() │ └ <Command main> └ <module 'uvicorn' from '/usr/local/lib/python3.11/site-packages/uvicorn/__init__.py'> File "/usr/local/lib/python3.11/site-packages/click/core.py", line 1514, in __call__ return self.main(*args, **kwargs) │ │ │ └ {} │ │ └ () │ └ <function Command.main at 0x14ade80ff240> └ <Command main> File "/usr/local/lib/python3.11/site-packages/click/core.py", line 1435, in main rv = self.invoke(ctx) │ │ └ <click.core.Context object at 0x14ade8df50d0> │ └ <function Command.invoke at 0x14ade80fef20> └ <Command main> File "/usr/local/lib/python3.11/site-packages/click/core.py", line 1298, in invoke return ctx.invoke(self.callback, **ctx.params) │ │ │ │ │ └ {'host': '0.0.0.0', 'port': 8080, 'forwarded_allow_ips': '*', 'workers': 1, 'app': 'open_webui.main:app', 'uds': None, 'fd': ... │ │ │ │ └ <click.core.Context object at 0x14ade8df50d0> │ │ │ └ <function main at 0x14ade7ed42c0> │ │ └ <Command main> │ └ <function Context.invoke at 0x14ade80fe160> └ <click.core.Context object at 0x14ade8df50d0> File "/usr/local/lib/python3.11/site-packages/click/core.py", line 853, in invoke return callback(*args, **kwargs) │ │ └ {'host': '0.0.0.0', 'port': 8080, 'forwarded_allow_ips': '*', 'workers': 1, 'app': 'open_webui.main:app', 'uds': None, 'fd': ... │ └ () └ <function main at 0x14ade7ed42c0> File "/usr/local/lib/python3.11/site-packages/uvicorn/main.py", line 433, in main run( └ <function run at 0x14ade7f95ee0> File "/usr/local/lib/python3.11/site-packages/uvicorn/main.py", line 606, in run server.run() │ └ <function Server.run at 0x14ade7f95760> └ <uvicorn.server.Server object at 0x14ade8133e50> File "/usr/local/lib/python3.11/site-packages/uvicorn/server.py", line 75, in run return asyncio_run(self.serve(sockets=sockets), loop_factory=self.config.get_loop_factory()) │ │ │ │ │ │ └ <function Config.get_loop_factory at 0x14ade80cc400> │ │ │ │ │ └ <uvicorn.config.Config object at 0x14ade7ed9c50> │ │ │ │ └ <uvicorn.server.Server object at 0x14ade8133e50> │ │ │ └ None │ │ └ <function Server.serve at 0x14ade7f95800> │ └ <uvicorn.server.Server object at 0x14ade8133e50> └ <function asyncio_run at 0x14ade8102200> File "/usr/local/lib/python3.11/site-packages/uvicorn/_compat.py", line 30, in asyncio_run return runner.run(main) │ │ └ <coroutine object Server.serve at 0x14ade7e3b1f0> │ └ <function Runner.run at 0x14ade8354fe0> └ <asyncio.runners.Runner object at 0x14ade7ee1590> File "/usr/local/lib/python3.11/asyncio/runners.py", line 118, in run return self._loop.run_until_complete(task) │ │ │ └ <Task pending name='Task-1' coro=<Server.serve() running at /usr/local/lib/python3.11/site-packages/uvicorn/server.py:79> wai... │ │ └ <cyfunction Loop.run_until_complete at 0x14ade7bfa740> │ └ <uvloop.Loop running=True closed=False debug=False> └ <asyncio.runners.Runner object at 0x14ade7ee1590> File "/app/backend/open_webui/main.py", line 1997, in process_chat return await process_chat_response(response, ctx) │ │ └ {'request': <starlette.requests.Request object at 0x14ad71a817d0>, 'form_data': {'stream': True, 'model': 'Gemma:31b', 'strea... │ └ <starlette.responses.StreamingResponse object at 0x14ad730893d0> └ <function process_chat_response at 0x14ad77514360> File "/app/backend/open_webui/utils/middleware.py", line 5204, in process_chat_response return await streaming_chat_response_handler(response, ctx) │ │ └ {'request': <starlette.requests.Request object at 0x14ad71a817d0>, 'form_data': {'stream': True, 'model': 'Gemma:31b', 'strea... │ └ <starlette.responses.StreamingResponse object at 0x14ad730893d0> └ <function streaming_chat_response_handler at 0x14ad775142c0> File "/app/backend/open_webui/utils/middleware.py", line 5152, in streaming_chat_response_handler return await response_handler(response, events) │ │ └ [] │ └ <starlette.responses.StreamingResponse object at 0x14ad730893d0> └ <function streaming_chat_response_handler.<locals>.response_handler at 0x14ad095b3060> File "/app/backend/open_webui/utils/middleware.py", line 4599, in response_handler tool_result = await tool_function(**tool_function_params) │ └ {'image_urls': ['/api/v1/files/c3c9da27-194e-4c1d-9c14-532d487e74d9/content'], 'prompt': 'Insert the following translated Eng... └ <function edit_image at 0x14ad71dd5c60> File "/app/backend/open_webui/utils/tools.py", line 136, in new_function return await partial_func(*args, **kwargs) │ │ └ {'image_urls': ['/api/v1/files/c3c9da27-194e-4c1d-9c14-532d487e74d9/content'], 'prompt': 'Insert the following translated Eng... │ └ () └ functools.partial(<function edit_image at 0x14ad7753c5e0>, __request__=<starlette.requests.Request object at 0x14ad71a817d0>,... File "/app/backend/open_webui/tools/builtin.py", line 347, in edit_image images = await image_edits( └ <function image_edits at 0x14ad78270220> File "/app/backend/open_webui/routers/images.py", line 1069, in image_edits image_data, content_type = await get_image_data(image_url, headers) │ │ └ None │ └ 'http://host:8188/view?filename=Flux-2-Klein+Edit_00020_.png&subfolder=&type=output' └ <function get_image_data at 0x14ad7839f9c0> > File "/app/backend/open_webui/routers/images.py", line 446, in get_image_data validate_url(data) │ └ 'http://host:8188/view?filename=Flux-2-Klein+Edit_00020_.png&subfolder=&type=output' └ <function validate_url at 0x14ad7b3e5f80> File "/app/backend/open_webui/retrieval/web/utils.py", line 70, in validate_url raise ValueError(ERROR_MESSAGES.INVALID_URL) │ └ <ERROR_MESSAGES.INVALID_URL: 'Oops! The URL you provided is invalid. Please double-check and try again.'> └ <enum 'ERROR_MESSAGES'> ValueError: Oops! The URL you provided is invalid. Please double-check and try again. 2026-05-11 12:09:37.525 | ERROR | open_webui.tools.builtin:edit_image:388 - edit_image error: 400: [ERROR: 'NoneType' object has no attribute 'lower'] Traceback (most recent call last): File "/app/backend/open_webui/routers/images.py", line 1070, in image_edits _, url = await upload_image( └ <function upload_image at 0x14ad7839fe20> File "/app/backend/open_webui/routers/images.py", line 475, in upload_image image_format = mimetypes.guess_extension(content_type) │ │ └ None │ └ <function guess_extension at 0x14ade787f420> └ <module 'mimetypes' from '/usr/local/lib/python3.11/mimetypes.py'> File "/usr/local/lib/python3.11/mimetypes.py", line 347, in guess_extension return _db.guess_extension(type, strict) │ │ │ └ True │ │ └ None │ └ <function MimeTypes.guess_extension at 0x14ade787f060> └ <mimetypes.MimeTypes object at 0x14ad75ba4090> File "/usr/local/lib/python3.11/mimetypes.py", line 202, in guess_extension extensions = self.guess_all_extensions(type, strict) │ │ │ └ True │ │ └ None │ └ <function MimeTypes.guess_all_extensions at 0x14ade787efc0> └ <mimetypes.MimeTypes object at 0x14ad75ba4090> File "/usr/local/lib/python3.11/mimetypes.py", line 181, in guess_all_extensions type = type.lower() └ None AttributeError: 'NoneType' object has no attribute 'lower' During handling of the above exception, another exception occurred: Traceback (most recent call last): File "<frozen runpy>", line 198, in _run_module_as_main File "<frozen runpy>", line 88, in _run_code File "/usr/local/lib/python3.11/site-packages/uvicorn/__main__.py", line 4, in <module> uvicorn.main() │ └ <Command main> └ <module 'uvicorn' from '/usr/local/lib/python3.11/site-packages/uvicorn/__init__.py'> File "/usr/local/lib/python3.11/site-packages/click/core.py", line 1514, in __call__ return self.main(*args, **kwargs) │ │ │ └ {} │ │ └ () │ └ <function Command.main at 0x14ade80ff240> └ <Command main> File "/usr/local/lib/python3.11/site-packages/click/core.py", line 1435, in main rv = self.invoke(ctx) │ │ └ <click.core.Context object at 0x14ade8df50d0> │ └ <function Command.invoke at 0x14ade80fef20> └ <Command main> File "/usr/local/lib/python3.11/site-packages/click/core.py", line 1298, in invoke return ctx.invoke(self.callback, **ctx.params) │ │ │ │ │ └ {'host': '0.0.0.0', 'port': 8080, 'forwarded_allow_ips': '*', 'workers': 1, 'app': 'open_webui.main:app', 'uds': None, 'fd': ... │ │ │ │ └ <click.core.Context object at 0x14ade8df50d0> │ │ │ └ <function main at 0x14ade7ed42c0> │ │ └ <Command main> │ └ <function Context.invoke at 0x14ade80fe160> └ <click.core.Context object at 0x14ade8df50d0> File "/usr/local/lib/python3.11/site-packages/click/core.py", line 853, in invoke return callback(*args, **kwargs) │ │ └ {'host': '0.0.0.0', 'port': 8080, 'forwarded_allow_ips': '*', 'workers': 1, 'app': 'open_webui.main:app', 'uds': None, 'fd': ... │ └ () └ <function main at 0x14ade7ed42c0> File "/usr/local/lib/python3.11/site-packages/uvicorn/main.py", line 433, in main run( └ <function run at 0x14ade7f95ee0> File "/usr/local/lib/python3.11/site-packages/uvicorn/main.py", line 606, in run server.run() │ └ <function Server.run at 0x14ade7f95760> └ <uvicorn.server.Server object at 0x14ade8133e50> File "/usr/local/lib/python3.11/site-packages/uvicorn/server.py", line 75, in run return asyncio_run(self.serve(sockets=sockets), loop_factory=self.config.get_loop_factory()) │ │ │ │ │ │ └ <function Config.get_loop_factory at 0x14ade80cc400> │ │ │ │ │ └ <uvicorn.config.Config object at 0x14ade7ed9c50> │ │ │ │ └ <uvicorn.server.Server object at 0x14ade8133e50> │ │ │ └ None │ │ └ <function Server.serve at 0x14ade7f95800> │ └ <uvicorn.server.Server object at 0x14ade8133e50> └ <function asyncio_run at 0x14ade8102200> File "/usr/local/lib/python3.11/site-packages/uvicorn/_compat.py", line 30, in asyncio_run return runner.run(main) │ │ └ <coroutine object Server.serve at 0x14ade7e3b1f0> │ └ <function Runner.run at 0x14ade8354fe0> └ <asyncio.runners.Runner object at 0x14ade7ee1590> File "/usr/local/lib/python3.11/asyncio/runners.py", line 118, in run return self._loop.run_until_complete(task) │ │ │ └ <Task pending name='Task-1' coro=<Server.serve() running at /usr/local/lib/python3.11/site-packages/uvicorn/server.py:79> wai... │ │ └ <cyfunction Loop.run_until_complete at 0x14ade7bfa740> │ └ <uvloop.Loop running=True closed=False debug=False> └ <asyncio.runners.Runner object at 0x14ade7ee1590> File "/app/backend/open_webui/main.py", line 1997, in process_chat return await process_chat_response(response, ctx) │ │ └ {'request': <starlette.requests.Request object at 0x14ad71a817d0>, 'form_data': {'stream': True, 'model': 'Gemma:31b', 'strea... │ └ <starlette.responses.StreamingResponse object at 0x14ad730893d0> └ <function process_chat_response at 0x14ad77514360> File "/app/backend/open_webui/utils/middleware.py", line 5204, in process_chat_response return await streaming_chat_response_handler(response, ctx) │ │ └ {'request': <starlette.requests.Request object at 0x14ad71a817d0>, 'form_data': {'stream': True, 'model': 'Gemma:31b', 'strea... │ └ <starlette.responses.StreamingResponse object at 0x14ad730893d0> └ <function streaming_chat_response_handler at 0x14ad775142c0> File "/app/backend/open_webui/utils/middleware.py", line 5152, in streaming_chat_response_handler return await response_handler(response, events) │ │ └ [] │ └ <starlette.responses.StreamingResponse object at 0x14ad730893d0> └ <function streaming_chat_response_handler.<locals>.response_handler at 0x14ad095b3060> File "/app/backend/open_webui/utils/middleware.py", line 4599, in response_handler tool_result = await tool_function(**tool_function_params) │ └ {'image_urls': ['/api/v1/files/c3c9da27-194e-4c1d-9c14-532d487e74d9/content'], 'prompt': 'Insert the following translated Eng... └ <function edit_image at 0x14ad71dd5c60> File "/app/backend/open_webui/utils/tools.py", line 136, in new_function return await partial_func(*args, **kwargs) │ │ └ {'image_urls': ['/api/v1/files/c3c9da27-194e-4c1d-9c14-532d487e74d9/content'], 'prompt': 'Insert the following translated Eng... │ └ () └ functools.partial(<function edit_image at 0x14ad7753c5e0>, __request__=<starlette.requests.Request object at 0x14ad71a817d0>,... > File "/app/backend/open_webui/tools/builtin.py", line 347, in edit_image images = await image_edits( └ <function image_edits at 0x14ad78270220> File "/app/backend/open_webui/routers/images.py", line 1085, in image_edits raise HTTPException(status_code=400, detail=ERROR_MESSAGES.DEFAULT(error)) │ │ │ └ AttributeError("'NoneType' object has no attribute 'lower'") │ │ └ <function ERROR_MESSAGES.<lambda> at 0x14ade3dd89a0> │ └ <enum 'ERROR_MESSAGES'> └ <class 'fastapi.exceptions.HTTPException'> fastapi.exceptions.HTTPException: 400: [ERROR: 'NoneType' object has no attribute 'lower'] ### Additional Information edit_image was working perfectly in 0.9.2 I can also confirm that images are being created in ComfyUI
GiteaMirror added the bug label 2026-05-13 07:48:35 -05:00
Author
Owner

@owui-terminator[bot] commented on GitHub (May 11, 2026):

🔍 Related Issues Found

I found some existing issues that might be related. Please check if any of these are duplicates or contain helpful solutions:

  1. 🟣 #24271 issue: Image generation with ComfyUI failing in 0.9.2
    This is the most directly related prior report: ComfyUI image generation in Open WebUI 0.9.2 was also failing while attempting to upload/display the generated image. It likely shares the same ComfyUI-to-OpenWebUI image handling path that regressed again in 0.9.5.
    by jpbreda · bug

  2. 🟣 #20754 issue: New upload of an image does not work with image editing
    This issue is about the image editing flow choosing or handling the wrong reference image, which is adjacent to the same edit_image / image_edits code path. It may help if the 0.9.5 regression is due to how edited images are resolved after ComfyUI returns a file.
    by iChristGit · bug


💡 If your issue is a duplicate, please close it and add any additional details to the existing issue instead.

This comment was generated automatically. React with 👍 if helpful, 👎 if not.

<!-- gh-comment-id:4418152387 --> @owui-terminator[bot] commented on GitHub (May 11, 2026): <!-- terminator-bot:related-issues-reply --> 🔍 **Related Issues Found** I found some existing issues that might be related. Please check if any of these are duplicates or contain helpful solutions: 1. 🟣 [#24271](https://github.com/open-webui/open-webui/issues/24271) **issue: Image generation with ComfyUI failing in 0.9.2** *This is the most directly related prior report: ComfyUI image generation in Open WebUI 0.9.2 was also failing while attempting to upload/display the generated image. It likely shares the same ComfyUI-to-OpenWebUI image handling path that regressed again in 0.9.5.* *by jpbreda · `bug`* 2. 🟣 [#20754](https://github.com/open-webui/open-webui/issues/20754) **issue: New upload of an image does not work with image editing** *This issue is about the image editing flow choosing or handling the wrong reference image, which is adjacent to the same edit_image / image_edits code path. It may help if the 0.9.5 regression is due to how edited images are resolved after ComfyUI returns a file.* *by iChristGit · `bug`* --- 💡 If your issue is a duplicate, please close it and add any additional details to the existing issue instead. *This comment was generated automatically.* React with 👍 if helpful, 👎 if not.
Author
Owner

@littlelucky commented on GitHub (May 11, 2026):

image generation error from 0.9.5, the img was generated by comfyui but cannot transfer to front.
0.9.4 is ok

<!-- gh-comment-id:4422116996 --> @littlelucky commented on GitHub (May 11, 2026): image generation error from 0.9.5, the img was generated by comfyui but cannot transfer to front. 0.9.4 is ok
Author
Owner

@NinjaLane commented on GitHub (May 11, 2026):

I can confirm the same.

"edit_image was working perfectly in 0.9.2
I can also confirm that images are being created in ComfyUI"

<!-- gh-comment-id:4425438791 --> @NinjaLane commented on GitHub (May 11, 2026): I can confirm the same. "edit_image was working perfectly in 0.9.2 I can also confirm that images are being created in ComfyUI"
Author
Owner

@luciusbono commented on GitHub (May 12, 2026):

I also have this issue in 0.9.5, reverted to 0.9.3 and things are fine again.

<!-- gh-comment-id:4427089803 --> @luciusbono commented on GitHub (May 12, 2026): I also have this issue in 0.9.5, reverted to 0.9.3 and things are fine again.
Author
Owner

@dongfangzan commented on GitHub (May 12, 2026):

I can confirm this exact same issue on my side.

Root cause

This regression was introduced in v0.9.5 via PR #24518 ("Image generation URL validation"), which added validate_url() inside get_image_data(). While this hardening makes sense for externally-loaded images, it breaks the ComfyUI download path because:

  1. ComfyUI is commonly deployed on an internal/private network (e.g. 192.168.x.x).
  2. After the image is successfully generated, ComfyUI returns an internal download URL such as http://192.168.x.x:8188/view?filename=....
  3. get_image_data() calls validate_url() on that URL.
  4. With the default ENABLE_RAG_LOCAL_WEB_FETCH=false, validate_url rejects any URL that resolves to a private IP (127.0.0.0/8, 10.0.0.0/8, 192.168.0.0/16, etc.).
  5. get_image_data() catches the ValueError and returns (None, None).
  6. The caller (image_edits / image_generations) does not check for None and passes it straight to upload_image(..., content_type=None, ...).
  7. upload_image calls mimetypes.guess_extension(None), which triggers the 'NoneType' object has no attribute 'lower' crash.

So the image generation actually succeeds; the crash happens after generation, during the download phase.

Workaround that works for me

Set the environment variable in your OpenWebUI deployment:

ENABLE_RAG_LOCAL_WEB_FETCH=true

With this, validate_url() no longer blocks private IPs and ComfyUI images download normally.

However, this is a global switch—it disables SSRF protection for all web-fetch features (RAG web search, image loading, etc.), not just ComfyUI. It works as a short-term fix but is not ideal from a security standpoint.

Suggested proper fix

Either of these would solve the problem more cleanly:

  1. Skip validate_url() for URLs that originate from an internally-configured ComfyUI instance. Since the ComfyUI base URL is explicitly set by the admin, it carries no SSRF risk.
  2. Defensive null-check in the ComfyUI branches of image_generations / image_edits. If get_image_data() returns (None, None), log the failure and continue instead of passing None into upload_image.
<!-- gh-comment-id:4429572939 --> @dongfangzan commented on GitHub (May 12, 2026): I can confirm this exact same issue on my side. **Root cause** This regression was introduced in **v0.9.5** via PR #24518 ("Image generation URL validation"), which added `validate_url()` inside `get_image_data()`. While this hardening makes sense for externally-loaded images, it breaks the ComfyUI download path because: 1. ComfyUI is commonly deployed on an internal/private network (e.g. `192.168.x.x`). 2. After the image is successfully generated, ComfyUI returns an internal download URL such as `http://192.168.x.x:8188/view?filename=...`. 3. `get_image_data()` calls `validate_url()` on that URL. 4. With the default `ENABLE_RAG_LOCAL_WEB_FETCH=false`, `validate_url` rejects any URL that resolves to a private IP (`127.0.0.0/8`, `10.0.0.0/8`, `192.168.0.0/16`, etc.). 5. `get_image_data()` catches the `ValueError` and returns `(None, None)`. 6. The caller (`image_edits` / `image_generations`) does not check for `None` and passes it straight to `upload_image(..., content_type=None, ...)`. 7. `upload_image` calls `mimetypes.guess_extension(None)`, which triggers the `'NoneType' object has no attribute 'lower'` crash. So the image generation actually succeeds; the crash happens **after** generation, during the download phase. **Workaround that works for me** Set the environment variable in your OpenWebUI deployment: ```bash ENABLE_RAG_LOCAL_WEB_FETCH=true ``` With this, `validate_url()` no longer blocks private IPs and ComfyUI images download normally. However, this is a global switch—it disables SSRF protection for **all** web-fetch features (RAG web search, image loading, etc.), not just ComfyUI. It works as a short-term fix but is not ideal from a security standpoint. **Suggested proper fix** Either of these would solve the problem more cleanly: 1. **Skip `validate_url()` for URLs that originate from an internally-configured ComfyUI instance.** Since the ComfyUI base URL is explicitly set by the admin, it carries no SSRF risk. 2. **Defensive null-check in the ComfyUI branches of `image_generations` / `image_edits`.** If `get_image_data()` returns `(None, None)`, log the failure and `continue` instead of passing `None` into `upload_image`.
Author
Owner

@littlelucky commented on GitHub (May 12, 2026):

ENABLE_RAG_LOCAL_WEB_FETCH=true

this setting is OK

<!-- gh-comment-id:4429702743 --> @littlelucky commented on GitHub (May 12, 2026): ENABLE_RAG_LOCAL_WEB_FETCH=true this setting is OK
Author
Owner

@seamon67 commented on GitHub (May 12, 2026):

ENABLE_RAG_LOCAL_WEB_FETCH=true

this setting is OK

Was a UI Button added for this?

<!-- gh-comment-id:4432354354 --> @seamon67 commented on GitHub (May 12, 2026): > ENABLE_RAG_LOCAL_WEB_FETCH=true > > this setting is OK Was a UI Button added for this?
Author
Owner

@jpbreda commented on GitHub (May 12, 2026):

Came here with the exact same problem. Thanks for the workaround.

A local IP address for an instance running ComfyUI is a totally valid configuration for a sovereign AI setup.

<!-- gh-comment-id:4432949742 --> @jpbreda commented on GitHub (May 12, 2026): Came here with the exact same problem. Thanks for the workaround. A local IP address for an instance running ComfyUI is a totally valid configuration for a sovereign AI setup.
Author
Owner

@pfn commented on GitHub (May 13, 2026):

adding a new ERROR_MESSAGES.RAG_LOCAL_DISALLOWED would be good for this circumstance, and fixing the exception path so that it bubbles the error up to the front end would be good.

right now, the .lower on None is happening because None is passed to mimetypes.guess_extension, due to the failure to fetch from local

<!-- gh-comment-id:4438663477 --> @pfn commented on GitHub (May 13, 2026): adding a new ERROR_MESSAGES.RAG_LOCAL_DISALLOWED would be good for this circumstance, and fixing the exception path so that it bubbles the error up to the front end would be good. right now, the .lower on None is happening because None is passed to mimetypes.guess_extension, due to the failure to fetch from local
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/open-webui#74940