[PR #20239] [CLOSED] fix: image editing with uploaded images after file storage refactor #64371

Closed
opened 2026-05-06 09:54:50 -05:00 by GiteaMirror · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/open-webui/open-webui/pull/20239
Author: @Classic298
Created: 12/29/2025
Status: Closed

Base: devHead: image-fix


📝 Commits (5)

📊 Changes

7 files changed (+63 additions, -18 deletions)

View changed files

📝 backend/open_webui/routers/images.py (+47 -10)
📝 backend/open_webui/utils/middleware.py (+5 -1)
📝 src/lib/components/chat/Messages/ResponseMessage.svelte (+2 -2)
📝 src/lib/components/chat/Messages/UserMessage.svelte (+6 -2)
📝 src/lib/components/common/Collapsible.svelte (+1 -1)
📝 src/lib/components/notes/NoteEditor.svelte (+1 -1)
📝 src/lib/components/notes/NoteEditor/Controls.svelte (+1 -1)

📄 Description

Description

This PR fixes image handling issues that broke after the v0.42/v0.43 refactoring which changed how images are stored in chats. Previously, images were stored as base64 data directly in the chat JSON. After the refactor, images are stored as Files in the database and referenced in the chat JSON as URLs (file IDs) for page loading speedup and caching benefits.

This change inadvertently broke:

  1. Image editing - backend code was not updated to handle the new image storage format
  2. Image display - uploaded images were displayed as file icons instead of actual images in several UI locations
  3. Edit mode preview - pasting/uploading images while editing a message showed broken previews

Root Cause Analysis

Bug 1: get_images_from_messages only checked type == "image"

Location: backend/open_webui/utils/middleware.py

The function extracts images from chat messages to determine whether to trigger image editing vs image generation. It only checked for file.get("type") == "image".

However, when images are uploaded through the file upload API (non-temporary chats), they are stored with:

  • type: 'file' (not 'image')
  • content_type: 'image/png' (or other image MIME type)
  • url: '{file_id}'

This caused uploaded images to be completely ignored, resulting in the image generation path being taken instead of image editing.

Bug 2: load_url_image didn't handle raw file IDs

Location: backend/open_webui/routers/images.py

The load_url_image function converts image URLs to base64 data before sending to the image editing API. It handled:

  • URLs starting with http:// or https://
  • URLs starting with /api/v1/files
  • Base64 data URLs (returned as-is)

However, when an image is uploaded via the file upload API, the frontend sets file.url to just the file ID (e.g., abc123-def456-...), not a full URL path. This caused the function to return the raw file ID unchanged, which is not valid image data for the editing API.

Bug 3: Frontend only checked type === 'image' in multiple components

Location: Multiple frontend components

Several components only checked file.type === 'image' without also checking content_type, causing uploaded images to be displayed as generic file icons instead of actual image previews.

Bug 4: Edit mode used file.url directly without URL transformation

Location: src/lib/components/chat/Messages/UserMessage.svelte

When editing a message and pasting/uploading an image, the edit mode was using file.url directly (which could be a raw file ID) instead of constructing the proper API URL, resulting in broken image previews.

Changes Made

Backend

1. backend/open_webui/utils/middleware.py

Updated get_images_from_messages() to also check for content_type starting with 'image/':

# Before
if file.get("type") == "image":

# After  
if file.get("type") == "image" or (
    file.get("content_type") or ""
).startswith("image/"):

2. backend/open_webui/routers/images.py

Updated load_url_image() to handle raw file IDs by attempting to retrieve the file content:

else:
    # Assume it's a raw file ID (frontend sends file.url = file_id)
    try:
        file_response = await get_file_content_by_id(data, user)
        if isinstance(file_response, FileResponse):
            # Read file and convert to base64
            ...
    except Exception:
        pass

Frontend

3. Updated image type detection in multiple components

Added content_type check to match the pattern already used in Chat.svelte and MessageInput.svelte:

File Change
UserMessage.svelte (edit mode) Added content_type check
ResponseMessage.svelte Added content_type check
Collapsible.svelte Added content_type check
NoteEditor.svelte Added content_type check
NoteEditor/Controls.svelte Added content_type check
<!-- Before -->
{#if file.type === 'image'}
<!-- After -->
{#if file.type === 'image' || (file?.content_type ?? '').startsWith('image/')}
  1. UserMessage.svelte - Fixed edit mode image preview URL
    Added URL transformation to edit mode to handle raw file IDs:
{@const fileUrl =
    file.url.startsWith('data') || file.url.startsWith('http')
        ? file.url
        : `${WEBUI_API_BASE_URL}/files/${file.url}${file?.content_type ? '/content' : ''}

Additional Notes

  • This fix is backward compatible - it still handles the old type: 'image' format for temporary chats where images are stored as base64 data URLs
  • The fix aligns backend and all frontend components with the consistent pattern for identifying images using both type and content_type
  • Fixes [PR #274] [MERGED] doc: feature update (#20237)

Contributor License Agreement

By submitting this pull request, I confirm that I have read and fully agree to the Contributor License Agreement (CLA), and I am providing my contributions under its terms.

Note

Deleting the CLA section will lead to immediate closure of your PR and it will not be merged in.


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/open-webui/open-webui/pull/20239 **Author:** [@Classic298](https://github.com/Classic298) **Created:** 12/29/2025 **Status:** ❌ Closed **Base:** `dev` ← **Head:** `image-fix` --- ### 📝 Commits (5) - [`a0da16d`](https://github.com/open-webui/open-webui/commit/a0da16dd080197eaa6c437654755657684988041) fix: image editing with uploaded images after file storage refactor - [`725d7bd`](https://github.com/open-webui/open-webui/commit/725d7bd5cc6b6d5d4e55c89ab4fcc8a0c154e95e) Claude/fix image editing l qq9 n (#138) - [`d186224`](https://github.com/open-webui/open-webui/commit/d18622475606b6b094adf7c274ebf617a0a289d9) Claude/fix image editing l qq9 n (#139) - [`ca71b78`](https://github.com/open-webui/open-webui/commit/ca71b78ccea12b7499c830d93b88e16b5ae48cde) fix - [`48fda8e`](https://github.com/open-webui/open-webui/commit/48fda8e37c883a9ae706d7b040f1a2ec664d158f) fix ### 📊 Changes **7 files changed** (+63 additions, -18 deletions) <details> <summary>View changed files</summary> 📝 `backend/open_webui/routers/images.py` (+47 -10) 📝 `backend/open_webui/utils/middleware.py` (+5 -1) 📝 `src/lib/components/chat/Messages/ResponseMessage.svelte` (+2 -2) 📝 `src/lib/components/chat/Messages/UserMessage.svelte` (+6 -2) 📝 `src/lib/components/common/Collapsible.svelte` (+1 -1) 📝 `src/lib/components/notes/NoteEditor.svelte` (+1 -1) 📝 `src/lib/components/notes/NoteEditor/Controls.svelte` (+1 -1) </details> ### 📄 Description ## Description This PR fixes image handling issues that broke after the v0.42/v0.43 refactoring which changed how images are stored in chats. Previously, images were stored as base64 data directly in the chat JSON. After the refactor, images are stored as Files in the database and referenced in the chat JSON as URLs (file IDs) for page loading speedup and caching benefits. This change inadvertently broke: 1. **Image editing** - backend code was not updated to handle the new image storage format 2. **Image display** - uploaded images were displayed as file icons instead of actual images in several UI locations 3. **Edit mode preview** - pasting/uploading images while editing a message showed broken previews ## Root Cause Analysis ### Bug 1: `get_images_from_messages` only checked `type == "image"` **Location:** `backend/open_webui/utils/middleware.py` The function extracts images from chat messages to determine whether to trigger image editing vs image generation. It only checked for `file.get("type") == "image"`. However, when images are uploaded through the file upload API (non-temporary chats), they are stored with: - `type: 'file'` (not `'image'`) - `content_type: 'image/png'` (or other image MIME type) - `url: '{file_id}'` This caused uploaded images to be completely ignored, resulting in the image generation path being taken instead of image editing. ### Bug 2: `load_url_image` didn't handle raw file IDs **Location:** `backend/open_webui/routers/images.py` The `load_url_image` function converts image URLs to base64 data before sending to the image editing API. It handled: - URLs starting with `http://` or `https://` - URLs starting with `/api/v1/files` - Base64 data URLs (returned as-is) However, when an image is uploaded via the file upload API, the frontend sets `file.url` to just the file ID (e.g., `abc123-def456-...`), not a full URL path. This caused the function to return the raw file ID unchanged, which is not valid image data for the editing API. ### Bug 3: Frontend only checked `type === 'image'` in multiple components **Location:** Multiple frontend components Several components only checked `file.type === 'image'` without also checking `content_type`, causing uploaded images to be displayed as generic file icons instead of actual image previews. ### Bug 4: Edit mode used `file.url` directly without URL transformation **Location:** `src/lib/components/chat/Messages/UserMessage.svelte` When editing a message and pasting/uploading an image, the edit mode was using `file.url` directly (which could be a raw file ID) instead of constructing the proper API URL, resulting in broken image previews. ## Changes Made ### Backend #### 1. `backend/open_webui/utils/middleware.py` Updated `get_images_from_messages()` to also check for `content_type` starting with `'image/'`: ```python # Before if file.get("type") == "image": # After if file.get("type") == "image" or ( file.get("content_type") or "" ).startswith("image/"): ``` #### 2. backend/open_webui/routers/images.py Updated load_url_image() to handle raw file IDs by attempting to retrieve the file content: ``` else: # Assume it's a raw file ID (frontend sends file.url = file_id) try: file_response = await get_file_content_by_id(data, user) if isinstance(file_response, FileResponse): # Read file and convert to base64 ... except Exception: pass ``` #### Frontend #### 3. Updated image type detection in multiple components Added content_type check to match the pattern already used in Chat.svelte and MessageInput.svelte: File | Change -- | -- UserMessage.svelte (edit mode) | Added content_type check ResponseMessage.svelte | Added content_type check Collapsible.svelte | Added content_type check NoteEditor.svelte | Added content_type check NoteEditor/Controls.svelte | Added content_type check ``` <!-- Before --> {#if file.type === 'image'} ``` ``` <!-- After --> {#if file.type === 'image' || (file?.content_type ?? '').startsWith('image/')} ``` 4. UserMessage.svelte - Fixed edit mode image preview URL Added URL transformation to edit mode to handle raw file IDs: ``` {@const fileUrl = file.url.startsWith('data') || file.url.startsWith('http') ? file.url : `${WEBUI_API_BASE_URL}/files/${file.url}${file?.content_type ? '/content' : ''} ``` ### Additional Notes - This fix is backward compatible - it still handles the old type: 'image' format for temporary chats where images are stored as base64 data URLs - The fix aligns backend and all frontend components with the consistent pattern for identifying images using both type and content_type - Fixes #20237 ### Contributor License Agreement By submitting this pull request, I confirm that I have read and fully agree to the [Contributor License Agreement (CLA)](https://github.com/open-webui/open-webui/blob/main/CONTRIBUTOR_LICENSE_AGREEMENT), and I am providing my contributions under its terms. > [!NOTE] > Deleting the CLA section will lead to immediate closure of your PR and it will not be merged in. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
GiteaMirror added the pull-request label 2026-05-06 09:54:51 -05:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/open-webui#64371