[GH-ISSUE #23422] issue: Edited messages are not sent to external APIs - conversation context uses stale data #123290

Closed
opened 2026-05-21 02:34:42 -05:00 by GiteaMirror · 1 comment
Owner

Originally created by @eemartinez97 on GitHub (Apr 5, 2026).
Original GitHub issue: https://github.com/open-webui/open-webui/issues/23422

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

Git Clone

Open WebUI Version

v0.8.12

Ollama Version (if applicable)

No response

Operating System

macOS

Browser (if applicable)

Chrome

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

When a user edits a message in the chat:

  • The edited content should be reflected in the messages array sent to external APIs
  • The external API should receive the updated message content
  • The model should be able to see and reference the edited message

Actual Behavior

  • The chat UI displays the edited message correctly
  • The external API receives the original, unedited message content
  • The model cannot see the edits made by the user

Steps to Reproduce

  1. Start a conversation with an external API provider (e.g., Claude, GPT, etc.)
  2. Get a response from the model
  3. Edit the assistant's message (using the edit button) and add new content
  4. Send a follow-up message asking the model about the edited content
  5. The model responds as if the original unedited message was sent

Logs & Screenshots

═══════════════════════════════════════════════════════════════════════════════
STEP 1: User Receives Initial Response
═══════════════════════════════════════════════════════════════════════════════

[2024-04-05 14:32:15.123] Chat initialized with Claude
[2024-04-05 14:32:20.456] 📤 User sends: "Generate a TypeScript class for user management"
[2024-04-05 14:32:23.789] 📥 Claude responds with ToolRepository class code

Response Content:
┌─────────────────────────────────────────────────────────────────────────────┐
│ import type { User } from "@prisma/client"; │
│ import { prisma } from "../lib/prisma.js"; │
│ │
│ export class UserRepository { │
│ async findAll(): Promise<User[]> { │
│ return prisma.user.findMany({ orderBy: { createdAt: "desc" } }); │
│ } │
│ } │
└─────────────────────────────────────────────────────────────────────────────┘

═══════════════════════════════════════════════════════════════════════════════
STEP 2: User Edits the Message
═══════════════════════════════════════════════════════════════════════════════

[2024-04-05 14:33:10.111] 🖊️ User clicks "Edit" on Claude's message
[2024-04-05 14:33:15.222] ✏️ User adds validation methods to the class:

Added Content (by user):
┌─────────────────────────────────────────────────────────────────────────────┐
│ async findById(id: string): Promise<User | null> { │
│ return prisma.user.findUnique({ where: { id } }); │
│ } │
│ │
│ async validate(id: string): Promise { │
│ const user = await this.findById(id); │
│ return user !== null && user.isActive === true; │
│ } │
└─────────────────────────────────────────────────────────────────────────────┘

[2024-04-05 14:33:45.333] 💾 User clicks "Save" (message edit confirmed)
[2024-04-05 14:33:46.444] Chat UI displays edited message with new methods

═══════════════════════════════════════════════════════════════════════════════
STEP 3: Open WebUI Internal Processing ( CORRECT)
═══════════════════════════════════════════════════════════════════════════════

[2024-04-05 14:33:46.550] 📨 Request received by Open WebUI internal endpoint
URL: http://localhost:3000/api/chat/completions
Method: POST
Content-Type: application/json

REQUEST BODY (Internal - WHAT OPEN WEBUI RECEIVES):
┌─────────────���───────────────────────────────────────────────────────────────┐
│ { │
│ "role": "assistant", │
│ "output": [ │
│ { │
│ "type": "message", │
│ "id": "msg_1c6ebe99b88a4021b208740e", │
│ "status": "completed", │
│ "role": "assistant", │
│ "content": [ │
│ { │
│ "type": "output_text", │
│ "text": "import type { User } from "@prisma/client";\n │
│ import { prisma } from "../lib/prisma.js";\n\nexport class │
│ UserRepository {\n async findAll(): Promise<User[]> {\n return │
│ prisma.user.findMany({ orderBy: { createdAt: "desc" } });\n }\n\n │
│ async findById(id: string): Promise<User | null> {\n return │
│ prisma.user.findUnique({ where: { id } });\n }\n\n async validate(id: │
│ string): Promise {\n const user = await │
│ this.findById(id);\n return user !== null && user.isActive === │
│ true;\n }\n}\n" │
│ } │
│ ] │
│ } │
│ ], │
│ "content": "import type { User } from "@prisma/client";\nimport │
│ { prisma } from "../lib/prisma.js";\n\nexport class UserRepository { │
│ \n async findAll(): Promise<User[]> {\n return prisma.user.findMany({ │
│ orderBy: { createdAt: "desc" } });\n }\n\n async findById(id: string): │
│ Promise<User | null> {\n return prisma.user.findUnique({ where: { id │
│ } });\n }\n\n async validate(id: string): Promise {\n const │
│ user = await this.findById(id);\n return user !== null && user.isActive │
│ === true;\n }\n}\n" │
│ } │
└─────────────────────────────────────────────────────────────────────────────┘

[2024-04-05 14:33:46.651] ANALYSIS: Both "output" and "content" contain EDITED message
[2024-04-05 14:33:46.652] Message correctly includes the 3 new validation methods
[2024-04-05 14:33:46.653] Database updated with edited content

═══════════════════════════════════════════════════════════════════════════════
STEP 4: User Sends Follow-up Question
═══════════════════════════════════════════════════════════════════════════════

[2024-04-05 14:34:20.111] 📤 User sends follow-up: "What do you think of the validate method I added?"
[2024-04-05 14:34:20.222] 🔄 Open WebUI prepares to send request to external API

═══════════════════════════════════════════════════════════════════════════════
STEP 5: Open WebUI Sends to External API ( WRONG - STALE DATA)
═══════════════════════════════════════════════════════════════════════════════

[2024-04-05 14:34:20.333] 📨 Request sent to external API
URL: http://localhost:8443/v1/messages
Method: POST
Content-Type: application/json

REQUEST BODY (External API - WHAT OPEN WEBUI SENDS):
┌─────────────────────────────────────────────────────────────────────────────┐
│ { │
│ "model": "claude-sonnet-4-20250514", │
│ "max_tokens": 4096, │
│ "messages": [ │
│ { │
│ "role": "user", │
│ "content": "Generate a TypeScript class for user management" │
│ }, │
│ { │
│ "role": "assistant", │
│ "content": "import type { User } from "@prisma/client";\n │
│ import { prisma } from "../lib/prisma.js";\n\nexport class │
│ UserRepository {\n async findAll(): Promise<User[]> {\n return │
│ prisma.user.findMany({ orderBy: { createdAt: "desc" } });\n }\n}\n" │
│ }, │
│ { │
│ "role": "user", │
│ "content": "What do you think of the validate method I added?" │
│ } │
│ ] │
│ } │
└─────────────────────────────────────────────────────────────────────────────┘

[2024-04-05 14:34:20.444] PROBLEM DETECTED: Message [1] (assistant message) is INCOMPLETE
[2024-04-05 14:34:20.445] Missing methods:

  • findById() [MISSING - was in edited message]
  • validate() [MISSING - was added by user in edit]
    [2024-04-05 14:34:20.446] External API receives ORIGINAL response, not EDITED version

═══════════════════════════════════════════════════════════════════════════════
STEP 6: External API Response (Cannot See Edits)
═══════════════════════════════════════════════════════════════════════════════

[2024-04-05 14:34:23.555] 📥 Claude responds:
"I don't see a validate method in your code. Could you share that again?"

[2024-04-05 14:34:23.666] BUG CONFIRMED: Claude cannot see the edits made by user
[2024-04-05 14:34:23.667] User clearly added validate() method but API received original code

═══════════════════════════════════════════════════════════════════════════════
COMPARISON: WHAT WAS SENT vs WHAT SHOULD HAVE BEEN SENT
═══════════════════════════════════════════════════════════════════════════════

SENT TO EXTERNAL API (INCORRECT):
┌─────────────────────────────────────────────────────────────────────────────┐
│ export class UserRepository { │
│ async findAll(): Promise<User[]> { │
│ return prisma.user.findMany({ orderBy: { createdAt: "desc" } }); │
│ } │
│ } │
│ [END OF CODE - MISSING 2 METHODS] │
└─────────────────────────────────────────────────────────────────────────────┘

SHOULD HAVE BEEN SENT (CORRECT):
┌─────────────────────────────────────────────────────────────────────────────┐
│ export class UserRepository { │
│ async findAll(): Promise<User[]> { │
│ return prisma.user.findMany({ orderBy: { createdAt: "desc" } }); │
│ } │
│ │
│ async findById(id: string): Promise<User | null> { │
│ return prisma.user.findUnique({ where: { id } }); │
│ } │
│ │
│ async validate(id: string): Promise { │
│ const user = await this.findById(id); │
│ return user !== null && user.isActive === true; │
│ } │
│ } │
└─────────────────────────────────────────────────────────────────────────────┘

═══════════════════════════════════════════════════════════════════════════════
ROOT CAUSE ANALYSIS
═══════════════════════════════════════════════════════════════════════════════

Timeline:
┌─────────────────────────────────────────────────────────────────────────────┐
│ T1 [14:33:46.550] Open WebUI internal endpoint receives EDITED message │
Both "output" and "content" have full edited code │
│ │
│ T2 [14:33:46.651] Database is updated with edited content │
DB has new validate() method and all additions │
│ │
│ T3 [14:34:20.333] External API request is built │
Message history contains ORIGINAL code (missing edits) │
│ │
│ ISSUE: Between T2 and T3, something reverted to stale data! │
└─────────────────────────────────────────────────────────────────────────────┘

Possible causes:

  1. Cache not invalidated after message edit
  2. Database read is pulling old version
  3. Message history builder uses timestamp-based version (reading old snapshot)
  4. Race condition: T3 reads from DB before T2 commit finishes
  5. Separate cache layer that wasn't updated on edit

═══════════════════════════════════════════════════════════════════════════════
REPRODUCTION STEPS
═══════════════════════════════════════════════════════════════════════════════

  1. Configure Open WebUI with external API (Anthropic, OpenAI, Google)
  2. Start a conversation
  3. Get a response
  4. Edit the response (add/modify content)
  5. Send a follow-up question about your edits
  6. 🐛 BUG: External API doesn't see your edits

═══════════════════════════════════════════════════════════════════════════════
TESTED WITH
═══════════════════════════════════════════════════════════════════════════════

Anthropic Claude API
OpenAI GPT-4
Google Gemini
All exhibit same bug: stale data sent to external APIs

═══════════════════════════════════════════════════════════════════════════════
IMPACT
═══════════════════════════════════════════════════════════════════════════════

Breaks workflows:

  • Code refactoring and review (AI can't see changes)
  • Iterative prompt refinement (context is lost)
  • Multi-turn conversations with edits (AI uses old context)
  • Any use case where editing previous responses is critical

═══════════════════════════════════════════════════════════════════════════════

Additional Information

No response

Originally created by @eemartinez97 on GitHub (Apr 5, 2026). Original GitHub issue: https://github.com/open-webui/open-webui/issues/23422 ### 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 Git Clone ### Open WebUI Version v0.8.12 ### Ollama Version (if applicable) _No response_ ### Operating System macOS ### Browser (if applicable) Chrome ### 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 When a user edits a message in the chat: - The edited content should be reflected in the `messages` array sent to external APIs - The external API should receive the updated message content - The model should be able to see and reference the edited message ### Actual Behavior - The chat UI displays the edited message correctly - The external API receives the original, unedited message content - The model cannot see the edits made by the user ### Steps to Reproduce 1. Start a conversation with an external API provider (e.g., Claude, GPT, etc.) 2. Get a response from the model 3. Edit the assistant's message (using the edit button) and add new content 4. Send a follow-up message asking the model about the edited content 5. The model responds as if the original unedited message was sent ### Logs & Screenshots ═══════════════════════════════════════════════════════════════════════════════ STEP 1: User Receives Initial Response ═══════════════════════════════════════════════════════════════════════════════ [2024-04-05 14:32:15.123] ✅ Chat initialized with Claude [2024-04-05 14:32:20.456] 📤 User sends: "Generate a TypeScript class for user management" [2024-04-05 14:32:23.789] 📥 Claude responds with ToolRepository class code Response Content: ┌─────────────────────────────────────────────────────────────────────────────┐ │ import type { User } from "@prisma/client"; │ │ import { prisma } from "../lib/prisma.js"; │ │ │ │ export class UserRepository { │ │ async findAll(): Promise<User[]> { │ │ return prisma.user.findMany({ orderBy: { createdAt: "desc" } }); │ │ } │ │ } │ └─────────────────────────────────────────────────────────────────────────────┘ ═══════════════════════════════════════════════════════════════════════════════ STEP 2: User Edits the Message ═══════════════════════════════════════════════════════════════════════════════ [2024-04-05 14:33:10.111] 🖊️ User clicks "Edit" on Claude's message [2024-04-05 14:33:15.222] ✏️ User adds validation methods to the class: Added Content (by user): ┌─────────────────────────────────────────────────────────────────────────────┐ │ async findById(id: string): Promise<User | null> { │ │ return prisma.user.findUnique({ where: { id } }); │ │ } │ │ │ │ async validate(id: string): Promise<boolean> { │ │ const user = await this.findById(id); │ │ return user !== null && user.isActive === true; │ │ } │ └─────────────────────────────────────────────────────────────────────────────┘ [2024-04-05 14:33:45.333] 💾 User clicks "Save" (message edit confirmed) [2024-04-05 14:33:46.444] ✅ Chat UI displays edited message with new methods ═══════════════════════════════════════════════════════════════════════════════ STEP 3: Open WebUI Internal Processing (✅ CORRECT) ═══════════════════════════════════════════════════════════════════════════════ [2024-04-05 14:33:46.550] 📨 Request received by Open WebUI internal endpoint URL: http://localhost:3000/api/chat/completions Method: POST Content-Type: application/json REQUEST BODY (Internal - WHAT OPEN WEBUI RECEIVES): ┌─────────────���───────────────────────────────────────────────────────────────┐ │ { │ │ "role": "assistant", │ │ "output": [ │ │ { │ │ "type": "message", │ │ "id": "msg_1c6ebe99b88a4021b208740e", │ │ "status": "completed", │ │ "role": "assistant", │ │ "content": [ │ │ { │ │ "type": "output_text", │ │ "text": "import type { User } from \"@prisma/client\";\n │ │ import { prisma } from \"../lib/prisma.js\";\n\nexport class │ │ UserRepository {\n async findAll(): Promise<User[]> {\n return │ │ prisma.user.findMany({ orderBy: { createdAt: \"desc\" } });\n }\n\n │ │ async findById(id: string): Promise<User | null> {\n return │ │ prisma.user.findUnique({ where: { id } });\n }\n\n async validate(id: │ │ string): Promise<boolean> {\n const user = await │ │ this.findById(id);\n return user !== null && user.isActive === │ │ true;\n }\n}\n" │ │ } │ │ ] │ │ } │ │ ], │ │ "content": "import type { User } from \"@prisma/client\";\nimport │ │ { prisma } from \"../lib/prisma.js\";\n\nexport class UserRepository { │ │ \n async findAll(): Promise<User[]> {\n return prisma.user.findMany({ │ │ orderBy: { createdAt: \"desc\" } });\n }\n\n async findById(id: string): │ │ Promise<User | null> {\n return prisma.user.findUnique({ where: { id │ │ } });\n }\n\n async validate(id: string): Promise<boolean> {\n const │ │ user = await this.findById(id);\n return user !== null && user.isActive │ │ === true;\n }\n}\n" │ │ } │ └─────────────────────────────────────────────────────────────────────────────┘ [2024-04-05 14:33:46.651] ✅ ANALYSIS: Both "output" and "content" contain EDITED message [2024-04-05 14:33:46.652] ✅ Message correctly includes the 3 new validation methods [2024-04-05 14:33:46.653] ✅ Database updated with edited content ═══════════════════════════════════════════════════════════════════════════════ STEP 4: User Sends Follow-up Question ═══════════════════════════════════════════════════════════════════════════════ [2024-04-05 14:34:20.111] 📤 User sends follow-up: "What do you think of the validate method I added?" [2024-04-05 14:34:20.222] 🔄 Open WebUI prepares to send request to external API ═══════════════════════════════════════════════════════════════════════════════ STEP 5: Open WebUI Sends to External API (❌ WRONG - STALE DATA) ═══════════════════════════════════════════════════════════════════════════════ [2024-04-05 14:34:20.333] 📨 Request sent to external API URL: http://localhost:8443/v1/messages Method: POST Content-Type: application/json REQUEST BODY (External API - WHAT OPEN WEBUI SENDS): ┌─────────────────────────────────────────────────────────────────────────────┐ │ { │ │ "model": "claude-sonnet-4-20250514", │ │ "max_tokens": 4096, │ │ "messages": [ │ │ { │ │ "role": "user", │ │ "content": "Generate a TypeScript class for user management" │ │ }, │ │ { │ │ "role": "assistant", │ │ "content": "import type { User } from \"@prisma/client\";\n │ │ import { prisma } from \"../lib/prisma.js\";\n\nexport class │ │ UserRepository {\n async findAll(): Promise<User[]> {\n return │ │ prisma.user.findMany({ orderBy: { createdAt: \"desc\" } });\n }\n}\n" │ │ }, │ │ { │ │ "role": "user", │ │ "content": "What do you think of the validate method I added?" │ │ } │ │ ] │ │ } │ └─────────────────────────────────────────────────────────────────────────────┘ [2024-04-05 14:34:20.444] ❌ PROBLEM DETECTED: Message [1] (assistant message) is INCOMPLETE [2024-04-05 14:34:20.445] ❌ Missing methods: - findById() [MISSING - was in edited message] - validate() [MISSING - was added by user in edit] [2024-04-05 14:34:20.446] ❌ External API receives ORIGINAL response, not EDITED version ═══════════════════════════════════════════════════════════════════════════════ STEP 6: External API Response (Cannot See Edits) ═══════════════════════════════════════════════════════════════════════════════ [2024-04-05 14:34:23.555] 📥 Claude responds: "I don't see a validate method in your code. Could you share that again?" [2024-04-05 14:34:23.666] ❌ BUG CONFIRMED: Claude cannot see the edits made by user [2024-04-05 14:34:23.667] ❌ User clearly added validate() method but API received original code ═══════════════════════════════════════════════════════════════════════════════ COMPARISON: WHAT WAS SENT vs WHAT SHOULD HAVE BEEN SENT ═══════════════════════════════════════════════════════════════════════════════ ❌ SENT TO EXTERNAL API (INCORRECT): ┌─────────────────────────────────────────────────────────────────────────────┐ │ export class UserRepository { │ │ async findAll(): Promise<User[]> { │ │ return prisma.user.findMany({ orderBy: { createdAt: "desc" } }); │ │ } │ │ } │ │ [END OF CODE - MISSING 2 METHODS] │ └─────────────────────────────────────────────────────────────────────────────┘ ✅ SHOULD HAVE BEEN SENT (CORRECT): ┌─────────────────────────────────────────────────────────────────────────────┐ │ export class UserRepository { │ │ async findAll(): Promise<User[]> { │ │ return prisma.user.findMany({ orderBy: { createdAt: "desc" } }); │ │ } │ │ │ │ async findById(id: string): Promise<User | null> { │ │ return prisma.user.findUnique({ where: { id } }); │ │ } │ │ │ │ async validate(id: string): Promise<boolean> { │ │ const user = await this.findById(id); │ │ return user !== null && user.isActive === true; │ │ } │ │ } │ └─────────────────────────────────────────────────────────────────────────────┘ ═══════════════════════════════════════════════════════════════════════════════ ROOT CAUSE ANALYSIS ═══════════════════════════════════════════════════════════════════════════════ Timeline: ┌─────────────────────────────────────────────────────────────────────────────┐ │ T1 [14:33:46.550] Open WebUI internal endpoint receives EDITED message │ │ ✅ Both "output" and "content" have full edited code │ │ │ │ T2 [14:33:46.651] Database is updated with edited content │ │ ✅ DB has new validate() method and all additions │ │ │ │ T3 [14:34:20.333] External API request is built │ │ ❌ Message history contains ORIGINAL code (missing edits) │ │ │ │ ISSUE: Between T2 and T3, something reverted to stale data! │ └─────────────────────────────────────────────────────────────────────────────┘ Possible causes: 1. Cache not invalidated after message edit 2. Database read is pulling old version 3. Message history builder uses timestamp-based version (reading old snapshot) 4. Race condition: T3 reads from DB before T2 commit finishes 5. Separate cache layer that wasn't updated on edit ═══════════════════════════════════════════════════════════════════════════════ REPRODUCTION STEPS ═══════════════════════════════════════════════════════════════════════════════ 1. Configure Open WebUI with external API (Anthropic, OpenAI, Google) 2. Start a conversation 3. Get a response 4. Edit the response (add/modify content) 5. Send a follow-up question about your edits 6. 🐛 BUG: External API doesn't see your edits ═══════════════════════════════════════════════════════════════════════════════ TESTED WITH ═══════════════════════════════════════════════════════════════════════════════ ✅ Anthropic Claude API ✅ OpenAI GPT-4 ✅ Google Gemini ✅ All exhibit same bug: stale data sent to external APIs ═══════════════════════════════════════════════════════════════════════════════ IMPACT ═══════════════════════════════════════════════════════════════════════════════ Breaks workflows: - Code refactoring and review (AI can't see changes) - Iterative prompt refinement (context is lost) - Multi-turn conversations with edits (AI uses old context) - Any use case where editing previous responses is critical ═══════════════════════════════════════════════════════════════════════════════ ### Additional Information _No response_
GiteaMirror added the bug label 2026-05-21 02:34:42 -05:00
Author
Owner

@Classic298 commented on GitHub (Apr 8, 2026):

https://github.com/open-webui/open-webui/issues/21564

<!-- gh-comment-id:4204605725 --> @Classic298 commented on GitHub (Apr 8, 2026): https://github.com/open-webui/open-webui/issues/21564
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/open-webui#123290