[GH-ISSUE #15189] issue: Bug: Lack of Data Integrity Validation on Chat Model Causes Silent Failure and Frontend Deadlock #56159

Open
opened 2026-05-05 18:51:31 -05:00 by GiteaMirror · 15 comments
Owner

Originally created by @robotmikhro on GitHub (Jun 21, 2025).
Original GitHub issue: https://github.com/open-webui/open-webui/issues/15189

Check Existing Issues

  • I have searched the existing issues and discussions.
  • I am using the latest version of Open WebUI.

Installation Method

Git Clone

Open WebUI Version

0.6.15

Ollama Version (if applicable)

No response

Operating System

Ubuntu 22.04.5 LTS(Jammy Jellyfish)

Browser (if applicable)

Firefox 139.0.4 (64-bit)

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

Area: Backend, Frontend, Data Integrity

Description

The application's backend does not perform sufficient data integrity checks on the chat object model before persisting it to the database. This allows structurally inconsistent or corrupted chat data (e.g., messages with missing parentId links) to be saved without any errors or warnings being logged.

When the frontend subsequently attempts to render this structurally flawed data, its rendering logic enters an unrecoverable state, such as an infinite loop or a state management deadlock. This results in the UI hanging indefinitely on a loading spinner, preventing the user from ever viewing the chat.

This is a fundamental data handling issue, not just an import/export problem. The import feature is simply the most direct way to introduce this kind of corrupted data and reproduce the bug.

Expected Behavior

The application should be resilient to data inconsistencies:

  • Backend: Before saving a chat object, the backend must validate its structural integrity. It should repair common issues (like broken parent-child links) or reject the data with a clear error log if it's irrecoverably malformed.
  • Frontend: The UI components should be robust enough to handle minor data imperfections without entering a deadlock, ensuring the application remains responsive.

Reasoning: Root Cause Analysis

The core issue is a lack of data validation and sanitization in the backend logic that handles the Chat model, "MAYBE" within backend/open_webui/models/chats.py.

  1. The Vulnerability: The backend implicitly trusts the structural integrity of the chat JSON object it receives. It does not validate the parent-child relationships within the message tree. In the provided example, the message 23067407-327f-4167-bac6-5804080aed15 is an "orphan" message—it has no parentId key, and no other message lists it as a child. This process completes without any exceptions or warnings, as the backend logic does not currently validate the internal consistency of the chat tree.

  2. The Consequence: When the frontend fetches this chat, its rendering logic receives an inconsistent state. It may, for example, iterate over one list of messages while trying to look up relationships in a different, out-of-sync map. When it encounters an inconsistency like the orphan message, the logic to determine the next message to render or to build the conversational tree can enter an unrecoverable state. This results in a logical deadlock or an infinite loop, which prevents the rendering process from ever completing, causing the persistent loading indicator.

Actual Behavior

The application hangs indefinitely on a loading spinner.

A critical diagnostic detail is that this failure is silent. No errors are generated in the browser's developer console, and no relevant warnings or errors appear in the Open-WebUI backend logs during the import or subsequent access of the chat. This points to a logical deadlock in the frontend rendering process, triggered by data that was silently accepted as "valid" by the backend.

Steps to Reproduce

  1. Introduce a structurally inconsistent chat object into the database, for example, by using the "Import Chat" feature with the malformed JSON provided below.
  2. The import process will appear to succeed, as no validation is performed on the chat's internal structure.
  3. Attempt to open and view the newly imported chat from the chat list.

Example of Malformed Data to Reproduce the Bug

The following JSON data, with its full content, reliably triggers the bug. The key structural flaws are:

  1. The message 23067407-327f-4167-bac6-5804080aed15 is an "orphan" message, as it is missing the parentId key.
  2. The top-level messages array is out of sync with the history.messages map (it is missing the orphan message).
[
  {
    "id": "8a3351f4-79c1-4731-8826-d5783944b0c2",
    "user_id": "fe7bbdce-2468-4ce4-aa02-00edd8c48e76",
    "title": "Fitur Applicant",
    "chat": {
      "id": "",
      "title": "Fitur Applicant",
      "models": ["claude-4-sonnet-latest"],
      "params": {},
      "history": {
        "messages": {
          "2d16b51a-2ae5-433f-a8c9-dea4999a41e2": {
            "id": "2d16b51a-2ae5-433f-a8c9-dea4999a41e2",
            "parentId": null,
            "childrenIds": ["c3cd2a61-23cb-40d4-8898-8c6b72b2c155"],
            "role": "user",
            "content": "Anda adalah programmer/software engineer laravel 11 ahli, bertindaklah sebagaimana praktisi ahli bertindak. Anda juga harus teliti dan sangat berhati-hati. Selalu generate code terbaik yang clean dan readable menurut best practice. Anda juga harus berpikir straight to the poin dan tidak berhalusinasi. Dalam analisa kode, anda harus teliti dan pastikan tidak ada bagian yang luput dari inspeksi anda. Berikan penjelasan yang clear,detail,transparant.",
            "timestamp": 1750304687,
            "models": ["claude-4-sonnet-latest"]
          },
          "c3cd2a61-23cb-40d4-8898-8c6b72b2c155": {
            "parentId": "2d16b51a-2ae5-433f-a8c9-dea4999a41e2",
            "id": "c3cd2a61-23cb-40d4-8898-8c6b72b2c155",
            "childrenIds": [],
            "role": "assistant",
            "content": "I understand you're looking for Laravel 11 expertise. I'm ready to help you with Laravel development questions, code reviews, best practices, and any technical challenges you're facing.\n\nAs a Laravel specialist, I can assist with:\n- Clean, readable code following Laravel conventions\n- Performance optimization\n- Security best practices\n- Database design and Eloquent relationships\n- API development\n- Testing strategies\n- Architecture decisions\n\nWhat specific Laravel 11 task or problem would you like help with today? Please share your code, requirements, or questions and I'll provide detailed, practical solutions.",
            "model": "claude-4-sonnet-latest",
            "modelName": "Claude 4 Sonnet Exp",
            "modelIdx": 0,
            "timestamp": 1750304687,
            "lastSentence": "As a Laravel specialist, I can assist with:\nClean, readable code following Laravel conventions\nPerformance optimization\nSecurity best practices\nDatabase design and Eloquent relationships\nAPI development\nTesting strategies\nArchitecture decisions\nWhat specific Laravel 11 task or problem would you like help with today?",
            "usage": {
              "prompt_tokens": 508,
              "completion_tokens": 125,
              "total_tokens": 633,
              "prompt_tokens_details": {
                "cached_tokens": 0,
                "cache_creation_input_tokens": 0
              }
            },
            "done": true,
            "followUps": [
              "How can I optimize Eloquent query performance in Laravel 11 for large datasets?",
              "What's the best approach to implement multi-tenancy in a Laravel 11 application?",
              "Can you guide me on using Laravel 11's new Blade features effectively?",
              "How should I structure API resources for a RESTful Laravel 11 backend?",
              "What are the latest security practices for Laravel 11 authentication systems?"
            ]
          },
          "23067407-327f-4167-bac6-5804080aed15": {
            "model": "claude-4-sonnet-latest",
            "content": "I'm ready to review your form.blade.php code. However, I don't see the actual code content in your message. Could you please share the code from your form.blade.php file so I can analyze it and provide detailed feedback?\n\nOnce you share the code, I'll examine it for:\n- Laravel best practices compliance\n- Security considerations (CSRF protection, validation, etc.)\n- Code structure and readability\n- Potential improvements\n- Any issues that need attention\n\nPlease paste your form.blade.php code and I'll give you a thorough analysis.",
            "followUps": [
              "Could you check if my CSRF protection is implemented correctly in the form?",
              "How can I validate the form inputs in the controller using Laravel best practices?",
              "What are some tips to improve the readability and structure of my Blade form code?",
              "Are there any security vulnerabilities I should be aware of when handling form submissions in Laravel?",
              "Should I be using FormRequest classes for validation, and how do I set them up?"
            ]
          }
        },
        "currentId": "23067407-327f-4167-bac6-5804080aed15"
      },
      "messages": [
        {
          "id": "2d16b51a-2ae5-433f-a8c9-dea4999a41e2",
          "parentId": null,
          "childrenIds": ["c3cd2a61-23cb-40d4-8898-8c6b72b2c155"],
          "role": "user",
          "content": "Anda adalah programmer/software engineer laravel 11 ahli, bertindaklah sebagaimana praktisi ahli bertindak. Anda juga harus teliti dan sangat berhati-hati. Selalu generate code terbaik yang clean dan readable menurut best practice. Anda juga harus berpikir straight to the poin dan tidak berhalusinasi. Dalam analisa kode, anda harus teliti dan pastikan tidak ada bagian yang luput dari inspeksi anda. Berikan penjelasan yang clear,detail,transparant.",
          "timestamp": 1750304687,
          "models": ["claude-4-sonnet-latest"]
        },
        {
          "parentId": "2d16b51a-2ae5-433f-a8c9-dea4999a41e2",
          "id": "c3cd2a61-23cb-40d4-8898-8c6b72b2c155",
          "childrenIds": [],
          "role": "assistant",
          "content": "I understand you're looking for Laravel 11 expertise. I'm ready to help you with Laravel development questions, code reviews, best practices, and any technical challenges you're facing.\n\nAs a Laravel specialist, I can assist with:\n- Clean, readable code following Laravel conventions\n- Performance optimization\n- Security best practices\n- Database design and Eloquent relationships\n- API development\n- Testing strategies\n- Architecture decisions\n\nWhat specific Laravel 11 task or problem would you like help with today? Please share your code, requirements, or questions and I'll provide detailed, practical solutions.",
          "model": "claude-4-sonnet-latest",
          "modelName": "Claude 4 Sonnet Exp",
          "modelIdx": 0,
          "timestamp": 1750304687,
          "lastSentence": "As a Laravel specialist, I can assist with:\nClean, readable code following Laravel conventions\nPerformance optimization\nSecurity best practices\nDatabase design and Eloquent relationships\nAPI development\nTesting strategies\nArchitecture decisions\nWhat specific Laravel 11 task or problem would you like help with today?",
          "usage": {
            "prompt_tokens": 508,
            "completion_tokens": 125,
            "total_tokens": 633,
            "prompt_tokens_details": {
              "cached_tokens": 0,
              "cache_creation_input_tokens": 0
            }
          },
          "done": true,
          "followUps": [
            "How can I optimize Eloquent query performance in Laravel 11 for large datasets?",
            "What's the best approach to implement multi-tenancy in a Laravel 11 application?",
            "Can you guide me on using Laravel 11's new Blade features effectively?",
            "How should I structure API resources for a RESTful Laravel 11 backend?",
            "What are the latest security practices for Laravel 11 authentication systems?"
          ]
        }
      ],
      "tags": [],
      "timestamp": 1750304687862,
      "files": []
    },
    "updated_at": 1750307488,
    "created_at": 1750304687,
    "share_id": null,
    "archived": false,
    "pinned": false,
    "meta": {},
    "folder_id": null
  }
]

Screenshots

Image

Additional Information

This bug was identified through a detailed debugging process that revealed several key insights which may be helpful for the development team:

  1. Specific Nature of Data Corruption: The issue was traced back to a specific type of structural inconsistency in the chat's JSON data. The primary flaw was an "orphan" message object that completely lacked a parentId key, effectively detaching it from the conversational tree. This was compounded by the top-level messages array being out of sync with the history.messages map, as it did not contain the orphan message.

  2. Frontend Failure Mode is a Logical Deadlock, Not a Crash: A crucial observation is that this issue does not produce any errors in the browser's developer console. This indicates the problem is not a simple runtime TypeError from accessing an undefined property. Instead, it suggests the frontend's rendering logic enters an unrecoverable state—likely an infinite loop or a state management deadlock—when it tries to process the inconsistent message tree. It cannot determine the correct sequence of messages to render, and thus hangs.

Originally created by @robotmikhro on GitHub (Jun 21, 2025). Original GitHub issue: https://github.com/open-webui/open-webui/issues/15189 ### Check Existing Issues - [x] I have searched the existing issues and discussions. - [x] I am using the latest version of Open WebUI. ### Installation Method Git Clone ### Open WebUI Version 0.6.15 ### Ollama Version (if applicable) _No response_ ### Operating System Ubuntu 22.04.5 LTS(Jammy Jellyfish) ### Browser (if applicable) Firefox 139.0.4 (64-bit) ### 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 **Area:** Backend, Frontend, Data Integrity ### Description The application's backend does not perform sufficient data integrity checks on the chat object model before persisting it to the database. This allows structurally inconsistent or corrupted chat data (e.g., messages with missing `parentId` links) to be saved **without any errors or warnings being logged**. When the frontend subsequently attempts to render this structurally flawed data, its rendering logic enters an unrecoverable state, such as an infinite loop or a state management deadlock. This results in the UI hanging indefinitely on a loading spinner, preventing the user from ever viewing the chat. This is a fundamental data handling issue, not just an import/export problem. The import feature is simply the most direct way to introduce this kind of corrupted data and reproduce the bug. ### Expected Behavior The application should be resilient to data inconsistencies: - **Backend:** Before saving a chat object, the backend must validate its structural integrity. It should repair common issues (like broken parent-child links) or reject the data with a clear error log if it's irrecoverably malformed. - **Frontend:** The UI components should be robust enough to handle minor data imperfections without entering a deadlock, ensuring the application remains responsive. ### Reasoning: Root Cause Analysis The core issue is a **lack of data validation and sanitization in the backend logic** that handles the `Chat` model, "MAYBE" within `backend/open_webui/models/chats.py`. 1. **The Vulnerability:** The backend implicitly trusts the structural integrity of the `chat` JSON object it receives. It does not validate the parent-child relationships within the message tree. In the provided example, the message `23067407-327f-4167-bac6-5804080aed15` is an "orphan" message—it has no `parentId` key, and no other message lists it as a child. This process completes without any exceptions or warnings, as the backend logic does not currently validate the internal consistency of the chat tree. 2. **The Consequence:** When the frontend fetches this chat, its rendering logic receives an inconsistent state. It may, for example, iterate over one list of messages while trying to look up relationships in a different, out-of-sync map. When it encounters an inconsistency like the orphan message, the logic to determine the next message to render or to build the conversational tree can enter an unrecoverable state. This results in a logical deadlock or an infinite loop, which prevents the rendering process from ever completing, causing the persistent loading indicator. ### Actual Behavior The application hangs indefinitely on a loading spinner. **A critical diagnostic detail is that this failure is silent.** No errors are generated in the browser's developer console, and **no relevant warnings or errors appear in the Open-WebUI backend logs** during the import or subsequent access of the chat. This points to a logical deadlock in the frontend rendering process, triggered by data that was silently accepted as "valid" by the backend. ### Steps to Reproduce 1. Introduce a structurally inconsistent chat object into the database, for example, by using the "Import Chat" feature with the malformed JSON provided below. 2. The import process will appear to succeed, as no validation is performed on the chat's internal structure. 3. Attempt to open and view the newly imported chat from the chat list. ### Example of Malformed Data to Reproduce the Bug The following JSON data, with its full content, reliably triggers the bug. The key structural flaws are: 1. The message `23067407-327f-4167-bac6-5804080aed15` is an "orphan" message, as it is missing the `parentId` key. 2. The top-level `messages` array is out of sync with the `history.messages` map (it is missing the orphan message). ```json [ { "id": "8a3351f4-79c1-4731-8826-d5783944b0c2", "user_id": "fe7bbdce-2468-4ce4-aa02-00edd8c48e76", "title": "Fitur Applicant", "chat": { "id": "", "title": "Fitur Applicant", "models": ["claude-4-sonnet-latest"], "params": {}, "history": { "messages": { "2d16b51a-2ae5-433f-a8c9-dea4999a41e2": { "id": "2d16b51a-2ae5-433f-a8c9-dea4999a41e2", "parentId": null, "childrenIds": ["c3cd2a61-23cb-40d4-8898-8c6b72b2c155"], "role": "user", "content": "Anda adalah programmer/software engineer laravel 11 ahli, bertindaklah sebagaimana praktisi ahli bertindak. Anda juga harus teliti dan sangat berhati-hati. Selalu generate code terbaik yang clean dan readable menurut best practice. Anda juga harus berpikir straight to the poin dan tidak berhalusinasi. Dalam analisa kode, anda harus teliti dan pastikan tidak ada bagian yang luput dari inspeksi anda. Berikan penjelasan yang clear,detail,transparant.", "timestamp": 1750304687, "models": ["claude-4-sonnet-latest"] }, "c3cd2a61-23cb-40d4-8898-8c6b72b2c155": { "parentId": "2d16b51a-2ae5-433f-a8c9-dea4999a41e2", "id": "c3cd2a61-23cb-40d4-8898-8c6b72b2c155", "childrenIds": [], "role": "assistant", "content": "I understand you're looking for Laravel 11 expertise. I'm ready to help you with Laravel development questions, code reviews, best practices, and any technical challenges you're facing.\n\nAs a Laravel specialist, I can assist with:\n- Clean, readable code following Laravel conventions\n- Performance optimization\n- Security best practices\n- Database design and Eloquent relationships\n- API development\n- Testing strategies\n- Architecture decisions\n\nWhat specific Laravel 11 task or problem would you like help with today? Please share your code, requirements, or questions and I'll provide detailed, practical solutions.", "model": "claude-4-sonnet-latest", "modelName": "Claude 4 Sonnet Exp", "modelIdx": 0, "timestamp": 1750304687, "lastSentence": "As a Laravel specialist, I can assist with:\nClean, readable code following Laravel conventions\nPerformance optimization\nSecurity best practices\nDatabase design and Eloquent relationships\nAPI development\nTesting strategies\nArchitecture decisions\nWhat specific Laravel 11 task or problem would you like help with today?", "usage": { "prompt_tokens": 508, "completion_tokens": 125, "total_tokens": 633, "prompt_tokens_details": { "cached_tokens": 0, "cache_creation_input_tokens": 0 } }, "done": true, "followUps": [ "How can I optimize Eloquent query performance in Laravel 11 for large datasets?", "What's the best approach to implement multi-tenancy in a Laravel 11 application?", "Can you guide me on using Laravel 11's new Blade features effectively?", "How should I structure API resources for a RESTful Laravel 11 backend?", "What are the latest security practices for Laravel 11 authentication systems?" ] }, "23067407-327f-4167-bac6-5804080aed15": { "model": "claude-4-sonnet-latest", "content": "I'm ready to review your form.blade.php code. However, I don't see the actual code content in your message. Could you please share the code from your form.blade.php file so I can analyze it and provide detailed feedback?\n\nOnce you share the code, I'll examine it for:\n- Laravel best practices compliance\n- Security considerations (CSRF protection, validation, etc.)\n- Code structure and readability\n- Potential improvements\n- Any issues that need attention\n\nPlease paste your form.blade.php code and I'll give you a thorough analysis.", "followUps": [ "Could you check if my CSRF protection is implemented correctly in the form?", "How can I validate the form inputs in the controller using Laravel best practices?", "What are some tips to improve the readability and structure of my Blade form code?", "Are there any security vulnerabilities I should be aware of when handling form submissions in Laravel?", "Should I be using FormRequest classes for validation, and how do I set them up?" ] } }, "currentId": "23067407-327f-4167-bac6-5804080aed15" }, "messages": [ { "id": "2d16b51a-2ae5-433f-a8c9-dea4999a41e2", "parentId": null, "childrenIds": ["c3cd2a61-23cb-40d4-8898-8c6b72b2c155"], "role": "user", "content": "Anda adalah programmer/software engineer laravel 11 ahli, bertindaklah sebagaimana praktisi ahli bertindak. Anda juga harus teliti dan sangat berhati-hati. Selalu generate code terbaik yang clean dan readable menurut best practice. Anda juga harus berpikir straight to the poin dan tidak berhalusinasi. Dalam analisa kode, anda harus teliti dan pastikan tidak ada bagian yang luput dari inspeksi anda. Berikan penjelasan yang clear,detail,transparant.", "timestamp": 1750304687, "models": ["claude-4-sonnet-latest"] }, { "parentId": "2d16b51a-2ae5-433f-a8c9-dea4999a41e2", "id": "c3cd2a61-23cb-40d4-8898-8c6b72b2c155", "childrenIds": [], "role": "assistant", "content": "I understand you're looking for Laravel 11 expertise. I'm ready to help you with Laravel development questions, code reviews, best practices, and any technical challenges you're facing.\n\nAs a Laravel specialist, I can assist with:\n- Clean, readable code following Laravel conventions\n- Performance optimization\n- Security best practices\n- Database design and Eloquent relationships\n- API development\n- Testing strategies\n- Architecture decisions\n\nWhat specific Laravel 11 task or problem would you like help with today? Please share your code, requirements, or questions and I'll provide detailed, practical solutions.", "model": "claude-4-sonnet-latest", "modelName": "Claude 4 Sonnet Exp", "modelIdx": 0, "timestamp": 1750304687, "lastSentence": "As a Laravel specialist, I can assist with:\nClean, readable code following Laravel conventions\nPerformance optimization\nSecurity best practices\nDatabase design and Eloquent relationships\nAPI development\nTesting strategies\nArchitecture decisions\nWhat specific Laravel 11 task or problem would you like help with today?", "usage": { "prompt_tokens": 508, "completion_tokens": 125, "total_tokens": 633, "prompt_tokens_details": { "cached_tokens": 0, "cache_creation_input_tokens": 0 } }, "done": true, "followUps": [ "How can I optimize Eloquent query performance in Laravel 11 for large datasets?", "What's the best approach to implement multi-tenancy in a Laravel 11 application?", "Can you guide me on using Laravel 11's new Blade features effectively?", "How should I structure API resources for a RESTful Laravel 11 backend?", "What are the latest security practices for Laravel 11 authentication systems?" ] } ], "tags": [], "timestamp": 1750304687862, "files": [] }, "updated_at": 1750307488, "created_at": 1750304687, "share_id": null, "archived": false, "pinned": false, "meta": {}, "folder_id": null } ] ``` ### Screenshots ![Image](https://github.com/user-attachments/assets/b645014c-2539-4bcc-8514-fd912a33da53) ### Additional Information This bug was identified through a detailed debugging process that revealed several key insights which may be helpful for the development team: 1. **Specific Nature of Data Corruption:** The issue was traced back to a specific type of structural inconsistency in the chat's JSON data. The primary flaw was an "orphan" message object that completely lacked a `parentId` key, effectively detaching it from the conversational tree. This was compounded by the top-level `messages` array being out of sync with the `history.messages` map, as it did not contain the orphan message. 2. **Frontend Failure Mode is a Logical Deadlock, Not a Crash:** A crucial observation is that this issue **does not produce any errors in the browser's developer console**. This indicates the problem is not a simple runtime `TypeError` from accessing an `undefined` property. Instead, it suggests the frontend's rendering logic enters an unrecoverable state—likely an infinite loop or a state management deadlock—when it tries to process the inconsistent message tree. It cannot determine the correct sequence of messages to render, and thus hangs.
GiteaMirror added the bugconfirmed issue labels 2026-05-05 18:51:32 -05:00
Author
Owner

@usrlocalben commented on GitHub (Aug 10, 2025):

Related to #11536

<!-- gh-comment-id:3172360423 --> @usrlocalben commented on GitHub (Aug 10, 2025): Related to #11536
Author
Owner

@usrlocalben commented on GitHub (Aug 10, 2025):

Users of llama-swap may get corrupted chats due to the way it construes backend errors as API messages.

Example:

...
"messages": {
  {
    ...prior messages...
    "99999999-9999-9999-9999-999999999999": {
      "parentId": "...",
      "id": "99999999-9999-9999-9999-999999999999",
      "childrenIds": [],
      "role": "assistant",
      "content": "Last good message",
      "model": "...",
      "modelName": "...",
      "modelIdx": 0,
      "timestamp": 17999999999,
      "done": true
    },
    "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa": {
      "error": {
        "content": "502: unexpected EOF\n"
      }
    }
  },
  "currentId": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"
}
...

This gives the Loading... spinner in chat UI despite successful retrieval at all other levels (no errors in console, no network errors, no noise on server logs etc.)

edit: I may have been a bit to hasty to link it to llama-swap. Glancing over the code there I don't see what I expect to wrt. to the error block, so it may have been caused by open-webui itself.

<!-- gh-comment-id:3172362099 --> @usrlocalben commented on GitHub (Aug 10, 2025): Users of [llama-swap](https://github.com/mostlygeek/llama-swap) may get corrupted chats ~~due to the way it construes backend errors as API messages~~. Example: ```json ... "messages": { { ...prior messages... "99999999-9999-9999-9999-999999999999": { "parentId": "...", "id": "99999999-9999-9999-9999-999999999999", "childrenIds": [], "role": "assistant", "content": "Last good message", "model": "...", "modelName": "...", "modelIdx": 0, "timestamp": 17999999999, "done": true }, "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa": { "error": { "content": "502: unexpected EOF\n" } } }, "currentId": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" } ... ``` This gives the _Loading..._ spinner in chat UI despite successful retrieval at all other levels (no errors in console, no network errors, no noise on server logs etc.) edit: I may have been a bit to hasty to link it to llama-swap. Glancing over the code there I don't see what I expect to wrt. to the error block, so it may have been caused by open-webui itself.
Author
Owner

@YifengChenGeotab commented on GitHub (Sep 12, 2025):

I have encountered this another example of corrupted chat that can lead to this kind of silent failure and frontend deadlock. Hope someone will take a look at this bug since it has been months. @tjbck

`.history.messages[]:

"xxxxx-xxxxxx": {
"content": "......"
}`
however a normal message should look like this:
"yyy-yyyyyyy": {
"parentId": "zzz-zzzzzz",
"id": "...",
"childrenIds": [],
"role": "assistant",
"content": "...",
"model": "gpt-5",
"modelName": "GPT 5",
"modelIdx": 1,
"userContext": null,
"timestamp": 1756845175,
"lastSentence": "...",
"done": true
}

Image

<!-- gh-comment-id:3286569530 --> @YifengChenGeotab commented on GitHub (Sep 12, 2025): I have encountered this another example of corrupted chat that can lead to this kind of silent failure and frontend deadlock. Hope someone will take a look at this bug since it has been months. @tjbck `.history.messages[]: "xxxxx-xxxxxx": { "content": "......" }` however a normal message should look like this: "yyy-yyyyyyy": { "parentId": "zzz-zzzzzz", "id": "...", "childrenIds": [], "role": "assistant", "content": "...", "model": "gpt-5", "modelName": "GPT 5", "modelIdx": 1, "userContext": null, "timestamp": 1756845175, "lastSentence": "...", "done": true } ![Image](https://github.com/user-attachments/assets/d7cf6e5f-1ec0-4119-9b92-5a1308bfcf6d)
Author
Owner

@DaRacci commented on GitHub (Sep 25, 2025):

I'm experiencing the same, I have this happen seemingly at random maybe once a week; Restarting the webserver seems to fix this but its very annoying.

Similarly I've found that having a user configured mcpo server which is unreachable can also cause this.

<!-- gh-comment-id:3332809490 --> @DaRacci commented on GitHub (Sep 25, 2025): I'm experiencing the same, I have this happen seemingly at random maybe once a week; Restarting the webserver seems to fix this but its very annoying. Similarly I've found that having a user configured mcpo server which is unreachable can also cause this.
Author
Owner

@rgaricano commented on GitHub (Sep 25, 2025):

The basic structural checks but is quite limited, and as implement a full validation is "delicated",
I made a Chat Integrity Checker for help in managing this issues. It can be used for check & repair chat history. It have dry run config valve (to check without make changes) and debug level.

2 versions, as action function and as tool.

As I made for testing I added log entry for all chat processed, maybe the logging could be excesive.

Action Function: Check_Chats_Action_Function.py

Tool:

        """
        Check and repair chat structural integrity.

        :param chat_id: Specific chat ID to check (optional, if not provided checks all user chats)
        :param skip: Number of chats to skip for pagination (default: 0)
        :return: Summary report of the integrity check
        """

Valves:

        check_own_chats_only: bool = Field(
            default=True,
            description="If true, only check chats owned by the current user.",
        )
        dry_run: bool = Field(
            default=True, description="If true, only report issues without fixing them."
        )
        max_chats_per_run: int = Field(
            default=50, description="Maximum number of chats to process in one run."
        )
        log_level: Literal["DEBUG", "INFO", "WARNING", "ERROR"] = Field(
            default="INFO", description="Logging level for the function operations."
        )

v0.1.1 Edited, fixed some minor issue and added emitters:
Check_Chats_Tool.py

v0.1.2 Added param skip in tool (for processing chats starting at skip number )
(e.g. use Check Chats tool skip 200 )
Check_Chats_Tool_v0.1.2.py

v0.1.3 Added UserValves for easier config.
Check_Chats_Tool_v0.1.3.py

Example:
I check the chats with dry run and I detect a wrong one:

Image

I ask for check only this chat:

Image

I test it and efffectively it fails...loading

Image

I change the dry run valve (for make changes) & I ask for check and fix only this chat

Image

Image

Now I test the chat again... Fixed, I can see it correctly!

Image

<!-- gh-comment-id:3333298297 --> @rgaricano commented on GitHub (Sep 25, 2025): The basic structural checks but is quite limited, and as implement a full validation is "delicated", I made a Chat Integrity Checker for help in managing this issues. It can be used for check & repair chat history. It have dry run config valve (to check without make changes) and debug level. 2 versions, as action function and as tool. As I made for testing I added log entry for all chat processed, maybe the logging could be excesive. Action Function: [Check_Chats_Action_Function.py](https://github.com/user-attachments/files/22534428/Check_Chats_Action_Function.py) Tool: ``` """ Check and repair chat structural integrity. :param chat_id: Specific chat ID to check (optional, if not provided checks all user chats) :param skip: Number of chats to skip for pagination (default: 0) :return: Summary report of the integrity check """ ``` Valves: ``` check_own_chats_only: bool = Field( default=True, description="If true, only check chats owned by the current user.", ) dry_run: bool = Field( default=True, description="If true, only report issues without fixing them." ) max_chats_per_run: int = Field( default=50, description="Maximum number of chats to process in one run." ) log_level: Literal["DEBUG", "INFO", "WARNING", "ERROR"] = Field( default="INFO", description="Logging level for the function operations." ) ``` v0.1.1 Edited, fixed some minor issue and added emitters: [Check_Chats_Tool.py](https://github.com/user-attachments/files/22537060/Check_Chats_Tool.py) v0.1.2 Added param skip in tool (for processing chats starting at _skip number_ ) (e.g. `use Check Chats tool skip 200 `) [Check_Chats_Tool_v0.1.2.py](https://github.com/user-attachments/files/22539905/Check_Chats_Tool_v0.1.2.py) v0.1.3 Added UserValves for easier config. [Check_Chats_Tool_v0.1.3.py](https://github.com/user-attachments/files/22549218/Check_Chats_Tool_v0.1.3.py) Example: I check the chats with dry run and I detect a wrong one: ![Image](https://github.com/user-attachments/assets/675779e1-a5f2-47e0-af1b-8cd7d2cac837) I ask for check only this chat: ![Image](https://github.com/user-attachments/assets/dbe1a399-4196-454f-9618-fa3570a5f19c) I test it and efffectively it fails...loading ![Image](https://github.com/user-attachments/assets/fb0d98ce-9663-46ab-931a-12d145f23fc8) I change the dry run valve (for make changes) & I ask for check and fix only this chat ![Image](https://github.com/user-attachments/assets/14d7f671-f787-410f-8d1c-f901bc74ee0e) ![Image](https://github.com/user-attachments/assets/ea82a30b-5d62-4622-a274-b58e87a26d29) Now I test the chat again... Fixed, I can see it correctly! ![Image](https://github.com/user-attachments/assets/8668691a-89a6-44d6-b892-ad9685bc5776)
Author
Owner

@silentoplayz commented on GitHub (Jan 14, 2026):

I am able to reproduce the issue reported with the reproduction steps and the malformed JSON provided.

[
  {
    "id": "8a3351f4-79c1-4731-8826-d5783944b0c2",
    "user_id": "fe7bbdce-2468-4ce4-aa02-00edd8c48e76",
    "title": "Fitur Applicant",
    "chat": {
      "id": "",
      "title": "Fitur Applicant",
      "models": ["claude-4-sonnet-latest"],
      "params": {},
      "history": {
        "messages": {
          "2d16b51a-2ae5-433f-a8c9-dea4999a41e2": {
            "id": "2d16b51a-2ae5-433f-a8c9-dea4999a41e2",
            "parentId": null,
            "childrenIds": ["c3cd2a61-23cb-40d4-8898-8c6b72b2c155"],
            "role": "user",
            "content": "Anda adalah programmer/software engineer laravel 11 ahli, bertindaklah sebagaimana praktisi ahli bertindak. Anda juga harus teliti dan sangat berhati-hati. Selalu generate code terbaik yang clean dan readable menurut best practice. Anda juga harus berpikir straight to the poin dan tidak berhalusinasi. Dalam analisa kode, anda harus teliti dan pastikan tidak ada bagian yang luput dari inspeksi anda. Berikan penjelasan yang clear,detail,transparant.",
            "timestamp": 1750304687,
            "models": ["claude-4-sonnet-latest"]
          },
          "c3cd2a61-23cb-40d4-8898-8c6b72b2c155": {
            "parentId": "2d16b51a-2ae5-433f-a8c9-dea4999a41e2",
            "id": "c3cd2a61-23cb-40d4-8898-8c6b72b2c155",
            "childrenIds": [],
            "role": "assistant",
            "content": "I understand you're looking for Laravel 11 expertise. I'm ready to help you with Laravel development questions, code reviews, best practices, and any technical challenges you're facing.\n\nAs a Laravel specialist, I can assist with:\n- Clean, readable code following Laravel conventions\n- Performance optimization\n- Security best practices\n- Database design and Eloquent relationships\n- API development\n- Testing strategies\n- Architecture decisions\n\nWhat specific Laravel 11 task or problem would you like help with today? Please share your code, requirements, or questions and I'll provide detailed, practical solutions.",
            "model": "claude-4-sonnet-latest",
            "modelName": "Claude 4 Sonnet Exp",
            "modelIdx": 0,
            "timestamp": 1750304687,
            "lastSentence": "As a Laravel specialist, I can assist with:\nClean, readable code following Laravel conventions\nPerformance optimization\nSecurity best practices\nDatabase design and Eloquent relationships\nAPI development\nTesting strategies\nArchitecture decisions\nWhat specific Laravel 11 task or problem would you like help with today?",
            "usage": {
              "prompt_tokens": 508,
              "completion_tokens": 125,
              "total_tokens": 633,
              "prompt_tokens_details": {
                "cached_tokens": 0,
                "cache_creation_input_tokens": 0
              }
            },
            "done": true,
            "followUps": [
              "How can I optimize Eloquent query performance in Laravel 11 for large datasets?",
              "What's the best approach to implement multi-tenancy in a Laravel 11 application?",
              "Can you guide me on using Laravel 11's new Blade features effectively?",
              "How should I structure API resources for a RESTful Laravel 11 backend?",
              "What are the latest security practices for Laravel 11 authentication systems?"
            ]
          },
          "23067407-327f-4167-bac6-5804080aed15": {
            "model": "claude-4-sonnet-latest",
            "content": "I'm ready to review your form.blade.php code. However, I don't see the actual code content in your message. Could you please share the code from your form.blade.php file so I can analyze it and provide detailed feedback?\n\nOnce you share the code, I'll examine it for:\n- Laravel best practices compliance\n- Security considerations (CSRF protection, validation, etc.)\n- Code structure and readability\n- Potential improvements\n- Any issues that need attention\n\nPlease paste your form.blade.php code and I'll give you a thorough analysis.",
            "followUps": [
              "Could you check if my CSRF protection is implemented correctly in the form?",
              "How can I validate the form inputs in the controller using Laravel best practices?",
              "What are some tips to improve the readability and structure of my Blade form code?",
              "Are there any security vulnerabilities I should be aware of when handling form submissions in Laravel?",
              "Should I be using FormRequest classes for validation, and how do I set them up?"
            ]
          }
        },
        "currentId": "23067407-327f-4167-bac6-5804080aed15"
      },
      "messages": [
        {
          "id": "2d16b51a-2ae5-433f-a8c9-dea4999a41e2",
          "parentId": null,
          "childrenIds": ["c3cd2a61-23cb-40d4-8898-8c6b72b2c155"],
          "role": "user",
          "content": "Anda adalah programmer/software engineer laravel 11 ahli, bertindaklah sebagaimana praktisi ahli bertindak. Anda juga harus teliti dan sangat berhati-hati. Selalu generate code terbaik yang clean dan readable menurut best practice. Anda juga harus berpikir straight to the poin dan tidak berhalusinasi. Dalam analisa kode, anda harus teliti dan pastikan tidak ada bagian yang luput dari inspeksi anda. Berikan penjelasan yang clear,detail,transparant.",
          "timestamp": 1750304687,
          "models": ["claude-4-sonnet-latest"]
        },
        {
          "parentId": "2d16b51a-2ae5-433f-a8c9-dea4999a41e2",
          "id": "c3cd2a61-23cb-40d4-8898-8c6b72b2c155",
          "childrenIds": [],
          "role": "assistant",
          "content": "I understand you're looking for Laravel 11 expertise. I'm ready to help you with Laravel development questions, code reviews, best practices, and any technical challenges you're facing.\n\nAs a Laravel specialist, I can assist with:\n- Clean, readable code following Laravel conventions\n- Performance optimization\n- Security best practices\n- Database design and Eloquent relationships\n- API development\n- Testing strategies\n- Architecture decisions\n\nWhat specific Laravel 11 task or problem would you like help with today? Please share your code, requirements, or questions and I'll provide detailed, practical solutions.",
          "model": "claude-4-sonnet-latest",
          "modelName": "Claude 4 Sonnet Exp",
          "modelIdx": 0,
          "timestamp": 1750304687,
          "lastSentence": "As a Laravel specialist, I can assist with:\nClean, readable code following Laravel conventions\nPerformance optimization\nSecurity best practices\nDatabase design and Eloquent relationships\nAPI development\nTesting strategies\nArchitecture decisions\nWhat specific Laravel 11 task or problem would you like help with today?",
          "usage": {
            "prompt_tokens": 508,
            "completion_tokens": 125,
            "total_tokens": 633,
            "prompt_tokens_details": {
              "cached_tokens": 0,
              "cache_creation_input_tokens": 0
            }
          },
          "done": true,
          "followUps": [
            "How can I optimize Eloquent query performance in Laravel 11 for large datasets?",
            "What's the best approach to implement multi-tenancy in a Laravel 11 application?",
            "Can you guide me on using Laravel 11's new Blade features effectively?",
            "How should I structure API resources for a RESTful Laravel 11 backend?",
            "What are the latest security practices for Laravel 11 authentication systems?"
          ]
        }
      ],
      "tags": [],
      "timestamp": 1750304687862,
      "files": []
    },
    "updated_at": 1750307488,
    "created_at": 1750304687,
    "share_id": null,
    "archived": false,
    "pinned": false,
    "meta": {},
    "folder_id": null
  }
]

Screenshot

Image

I found out that if I open up the Chat Overview sidebar within this chat, I can see the message nodes. Clicking on either one fixes the view of the chat and likely patches out a corruption issue, as no error is thrown by clicking on either of the nodes. Leaving the chat and returning back to it is not an issue, so this appears to be a temporary issue that can easily be solved with at least this chat.

Image
<!-- gh-comment-id:3748563858 --> @silentoplayz commented on GitHub (Jan 14, 2026): I am able to reproduce the issue reported with the reproduction steps and the malformed JSON provided. ```json [ { "id": "8a3351f4-79c1-4731-8826-d5783944b0c2", "user_id": "fe7bbdce-2468-4ce4-aa02-00edd8c48e76", "title": "Fitur Applicant", "chat": { "id": "", "title": "Fitur Applicant", "models": ["claude-4-sonnet-latest"], "params": {}, "history": { "messages": { "2d16b51a-2ae5-433f-a8c9-dea4999a41e2": { "id": "2d16b51a-2ae5-433f-a8c9-dea4999a41e2", "parentId": null, "childrenIds": ["c3cd2a61-23cb-40d4-8898-8c6b72b2c155"], "role": "user", "content": "Anda adalah programmer/software engineer laravel 11 ahli, bertindaklah sebagaimana praktisi ahli bertindak. Anda juga harus teliti dan sangat berhati-hati. Selalu generate code terbaik yang clean dan readable menurut best practice. Anda juga harus berpikir straight to the poin dan tidak berhalusinasi. Dalam analisa kode, anda harus teliti dan pastikan tidak ada bagian yang luput dari inspeksi anda. Berikan penjelasan yang clear,detail,transparant.", "timestamp": 1750304687, "models": ["claude-4-sonnet-latest"] }, "c3cd2a61-23cb-40d4-8898-8c6b72b2c155": { "parentId": "2d16b51a-2ae5-433f-a8c9-dea4999a41e2", "id": "c3cd2a61-23cb-40d4-8898-8c6b72b2c155", "childrenIds": [], "role": "assistant", "content": "I understand you're looking for Laravel 11 expertise. I'm ready to help you with Laravel development questions, code reviews, best practices, and any technical challenges you're facing.\n\nAs a Laravel specialist, I can assist with:\n- Clean, readable code following Laravel conventions\n- Performance optimization\n- Security best practices\n- Database design and Eloquent relationships\n- API development\n- Testing strategies\n- Architecture decisions\n\nWhat specific Laravel 11 task or problem would you like help with today? Please share your code, requirements, or questions and I'll provide detailed, practical solutions.", "model": "claude-4-sonnet-latest", "modelName": "Claude 4 Sonnet Exp", "modelIdx": 0, "timestamp": 1750304687, "lastSentence": "As a Laravel specialist, I can assist with:\nClean, readable code following Laravel conventions\nPerformance optimization\nSecurity best practices\nDatabase design and Eloquent relationships\nAPI development\nTesting strategies\nArchitecture decisions\nWhat specific Laravel 11 task or problem would you like help with today?", "usage": { "prompt_tokens": 508, "completion_tokens": 125, "total_tokens": 633, "prompt_tokens_details": { "cached_tokens": 0, "cache_creation_input_tokens": 0 } }, "done": true, "followUps": [ "How can I optimize Eloquent query performance in Laravel 11 for large datasets?", "What's the best approach to implement multi-tenancy in a Laravel 11 application?", "Can you guide me on using Laravel 11's new Blade features effectively?", "How should I structure API resources for a RESTful Laravel 11 backend?", "What are the latest security practices for Laravel 11 authentication systems?" ] }, "23067407-327f-4167-bac6-5804080aed15": { "model": "claude-4-sonnet-latest", "content": "I'm ready to review your form.blade.php code. However, I don't see the actual code content in your message. Could you please share the code from your form.blade.php file so I can analyze it and provide detailed feedback?\n\nOnce you share the code, I'll examine it for:\n- Laravel best practices compliance\n- Security considerations (CSRF protection, validation, etc.)\n- Code structure and readability\n- Potential improvements\n- Any issues that need attention\n\nPlease paste your form.blade.php code and I'll give you a thorough analysis.", "followUps": [ "Could you check if my CSRF protection is implemented correctly in the form?", "How can I validate the form inputs in the controller using Laravel best practices?", "What are some tips to improve the readability and structure of my Blade form code?", "Are there any security vulnerabilities I should be aware of when handling form submissions in Laravel?", "Should I be using FormRequest classes for validation, and how do I set them up?" ] } }, "currentId": "23067407-327f-4167-bac6-5804080aed15" }, "messages": [ { "id": "2d16b51a-2ae5-433f-a8c9-dea4999a41e2", "parentId": null, "childrenIds": ["c3cd2a61-23cb-40d4-8898-8c6b72b2c155"], "role": "user", "content": "Anda adalah programmer/software engineer laravel 11 ahli, bertindaklah sebagaimana praktisi ahli bertindak. Anda juga harus teliti dan sangat berhati-hati. Selalu generate code terbaik yang clean dan readable menurut best practice. Anda juga harus berpikir straight to the poin dan tidak berhalusinasi. Dalam analisa kode, anda harus teliti dan pastikan tidak ada bagian yang luput dari inspeksi anda. Berikan penjelasan yang clear,detail,transparant.", "timestamp": 1750304687, "models": ["claude-4-sonnet-latest"] }, { "parentId": "2d16b51a-2ae5-433f-a8c9-dea4999a41e2", "id": "c3cd2a61-23cb-40d4-8898-8c6b72b2c155", "childrenIds": [], "role": "assistant", "content": "I understand you're looking for Laravel 11 expertise. I'm ready to help you with Laravel development questions, code reviews, best practices, and any technical challenges you're facing.\n\nAs a Laravel specialist, I can assist with:\n- Clean, readable code following Laravel conventions\n- Performance optimization\n- Security best practices\n- Database design and Eloquent relationships\n- API development\n- Testing strategies\n- Architecture decisions\n\nWhat specific Laravel 11 task or problem would you like help with today? Please share your code, requirements, or questions and I'll provide detailed, practical solutions.", "model": "claude-4-sonnet-latest", "modelName": "Claude 4 Sonnet Exp", "modelIdx": 0, "timestamp": 1750304687, "lastSentence": "As a Laravel specialist, I can assist with:\nClean, readable code following Laravel conventions\nPerformance optimization\nSecurity best practices\nDatabase design and Eloquent relationships\nAPI development\nTesting strategies\nArchitecture decisions\nWhat specific Laravel 11 task or problem would you like help with today?", "usage": { "prompt_tokens": 508, "completion_tokens": 125, "total_tokens": 633, "prompt_tokens_details": { "cached_tokens": 0, "cache_creation_input_tokens": 0 } }, "done": true, "followUps": [ "How can I optimize Eloquent query performance in Laravel 11 for large datasets?", "What's the best approach to implement multi-tenancy in a Laravel 11 application?", "Can you guide me on using Laravel 11's new Blade features effectively?", "How should I structure API resources for a RESTful Laravel 11 backend?", "What are the latest security practices for Laravel 11 authentication systems?" ] } ], "tags": [], "timestamp": 1750304687862, "files": [] }, "updated_at": 1750307488, "created_at": 1750304687, "share_id": null, "archived": false, "pinned": false, "meta": {}, "folder_id": null } ] ``` ### Screenshot <img width="2556" height="1273" alt="Image" src="https://github.com/user-attachments/assets/ef3f2bcd-731f-475e-be0f-4009b0de9aee" /> ### I found out that if I open up the `Chat Overview` sidebar within this chat, I can see the message nodes. Clicking on either one fixes the view of the chat and likely patches out a corruption issue, as no error is thrown by clicking on either of the nodes. Leaving the chat and returning back to it is not an issue, so this appears to be a temporary issue that can easily be solved with *at least* this chat. <img width="2556" height="1273" alt="Image" src="https://github.com/user-attachments/assets/1737175f-657e-41ad-a516-7ab7809511e5" />
Author
Owner

@silentoplayz commented on GitHub (Jan 14, 2026):

@rgaricano Thanks for sharing this and for creating the Check Chats Tool! I gave it a dry run against all my chats and the tool detected 7 invalid chats throughout all my chats!

Image

I manually visited each chat URL to verify the detections and each chat pointed out did indeed have the described issue.

I toggled off Dry Mode and let the tool fix the broken chats. Whether or not it truly fixed all of them, I couldn't tell you for sure, as I made the decision to delete all of the broken chats the tool had found throughout my chats list.
Image

<!-- gh-comment-id:3748729098 --> @silentoplayz commented on GitHub (Jan 14, 2026): @rgaricano Thanks for sharing this and for creating the Check Chats Tool! I gave it a dry run against all my chats and the tool detected 7 invalid chats throughout all my chats! <img width="1513" height="1189" alt="Image" src="https://github.com/user-attachments/assets/f0981680-6a76-4482-b905-650210087b51" /> I manually visited each chat URL to verify the detections and each chat pointed out did indeed have the described issue. I toggled off `Dry Mode` and let the tool fix the broken chats. Whether or not it truly fixed all of them, I couldn't tell you for sure, as I made the decision to delete all of the broken chats the tool had found throughout my chats list. <img width="2028" height="1282" alt="Image" src="https://github.com/user-attachments/assets/db2a2788-a775-48a8-aae6-b5e60a66d584" />
Author
Owner

@silentoplayz commented on GitHub (Feb 21, 2026):

Semi-related PR - https://github.com/open-webui/open-webui/pull/21681

<!-- gh-comment-id:3937884338 --> @silentoplayz commented on GitHub (Feb 21, 2026): Semi-related PR - https://github.com/open-webui/open-webui/pull/21681
Author
Owner

@ghost commented on GitHub (Apr 27, 2026):

Image

how is this .py extension supposed to be imported as function if its not in json format even?

@rgaricano

<!-- gh-comment-id:4331083774 --> @ghost commented on GitHub (Apr 27, 2026): <img width="692" height="236" alt="Image" src="https://github.com/user-attachments/assets/83015f86-e2e4-46e1-8d8a-ed5a26b16f8d" /> how is this .py extension supposed to be imported as function if its not in json format even? @rgaricano
Author
Owner

@ghost commented on GitHub (Apr 27, 2026):

{"error":"Error during chat integrity check: object of type 'coroutine' has no len()"}

<!-- gh-comment-id:4331122899 --> @ghost commented on GitHub (Apr 27, 2026): {"error":"Error during chat integrity check: object of type 'coroutine' has no len()"}
Author
Owner

@ghost commented on GitHub (Apr 27, 2026):

Image
<!-- gh-comment-id:4331203917 --> @ghost commented on GitHub (Apr 27, 2026): <img width="941" height="491" alt="Image" src="https://github.com/user-attachments/assets/4466a797-b7cc-444a-a3fa-30e12523cd78" />
Author
Owner

@ghost commented on GitHub (Apr 27, 2026):

use chats check tools for check chat id xxxx

be careful while using this tool it just reset my old chat to basically very first message lol
nice lost chat

Image
<!-- gh-comment-id:4331256135 --> @ghost commented on GitHub (Apr 27, 2026): ``` use chats check tools for check chat id xxxx ``` be careful while using this tool it just reset my old chat to basically very first message lol nice lost chat <img width="976" height="736" alt="Image" src="https://github.com/user-attachments/assets/c212310e-1ba0-4e9d-babf-d82013cf5ff5" />
Author
Owner

@ghost commented on GitHub (Apr 27, 2026):

from __future__ import annotations
from pydantic import BaseModel, Field
from typing import Optional, Dict, List, Any, Literal
import json
import logging


class Tools:
    class Valves(BaseModel):
        dry_run: bool = Field(
            default=True, description="If true, only report issues without fixing them."
        )
        max_chats_per_run: int = Field(
            default=50, description="Maximum number of chats to process in one run."
        )
        log_level: Literal["DEBUG", "INFO", "WARNING", "ERROR"] = Field(
            default="INFO", description="Logging level for the function operations."
        )

    class UserValves(BaseModel):
        check_own_chats_only: bool = Field(
            default=True,
            description="If true, only check chats owned by the current user.",
        )
        dry_run: bool = Field(
            default=True, description="If true, only report issues without fixing them."
        )
        max_chats_per_run: int = Field(
            default=50, description="Maximum number of chats to process in one run."
        )
        log_level: Literal["DEBUG", "INFO", "WARNING", "ERROR"] = Field(
            default="INFO", description="Logging level for the function operations."
        )

    def __init__(self):
        self.valves = self.Valves()
        self.logger = logging.getLogger(__name__)

    def validate_and_repair_chat(self, chat_data: Dict[str, Any]) -> Dict[str, Any]:
        """Validate and repair a single chat's structural integrity."""
        report = {
            "isValid": True,
            "errors": [],
            "warnings": [],
            "repaired": False,
            "repairedIssues": [],
        }

        # Check if chat has required structure
        if not chat_data or not isinstance(chat_data, dict):
            report["errors"].append("Chat object is null or not a dictionary")
            report["isValid"] = False
            return report

        # Validate history structure
        history = chat_data.get("history", {})
        if not isinstance(history, dict):
            report["errors"].append("Chat history is missing or invalid")
            report["isValid"] = False
            return report

        messages = history.get("messages", {})
        current_id = history.get("currentId")

        if not isinstance(messages, dict):
            report["errors"].append("Messages object is missing or invalid")
            report["isValid"] = False
            return report

        message_ids = list(messages.keys())
        if len(message_ids) == 0:
            report["warnings"].append("Chat has no messages")
            return report

        # Track relationships for repair
        orphaned_messages = []
        invalid_messages = []
        root_messages = []

        # First pass: validate individual messages
        for message_id in message_ids:
            message = messages[message_id]

            if not isinstance(message, dict):
                report["errors"].append(f"Message {message_id} is not a dictionary")
                invalid_messages.append(message_id)
                continue

            # Check required fields
            if not message.get("id") or message["id"] != message_id:
                if message.get("id") and message["id"] != message_id:
                    report["warnings"].append(
                        f"Message ID mismatch: key={message_id}, id={message.get('id')}"
                    )
                    if not self.valves.dry_run:
                        message["id"] = message_id
                        report["repaired"] = True
                        report["repairedIssues"].append(
                            f"Fixed ID mismatch for message {message_id}"
                        )
                else:
                    if not self.valves.dry_run:
                        message["id"] = message_id
                        report["repaired"] = True
                        report["repairedIssues"].append(
                            f"Added missing ID for message {message_id}"
                        )

            # Validate content
            if not isinstance(message.get("content"), str):
                if message.get("content") is None:
                    if not self.valves.dry_run:
                        message["content"] = ""
                        report["repaired"] = True
                        report["repairedIssues"].append(
                            f"Fixed null content for message {message_id}"
                        )
                else:
                    report["errors"].append(
                        f"Message {message_id} has invalid content type"
                    )
                    invalid_messages.append(message_id)
                    continue

            # Validate role
            if message.get("role") not in ["user", "assistant", "system"]:
                report["errors"].append(
                    f"Message {message_id} has invalid role: {message.get('role')}"
                )
                invalid_messages.append(message_id)
                continue

            # Initialize childrenIds if missing
            if not isinstance(message.get("childrenIds"), list):
                if not self.valves.dry_run:
                    message["childrenIds"] = []
                    report["repaired"] = True
                    report["repairedIssues"].append(
                        f"Fixed missing childrenIds for message {message_id}"
                    )

        # Remove invalid messages (if not dry run)
        if not self.valves.dry_run:
            for invalid_id in invalid_messages:
                del messages[invalid_id]
                report["repaired"] = True
                report["repairedIssues"].append(f"Removed invalid message {invalid_id}")

        # Second pass: validate parent-child relationships
        valid_message_ids = [mid for mid in message_ids if mid not in invalid_messages]

        for message_id in valid_message_ids:
            message = messages[message_id]
            parent_id = message.get("parentId")

            # Check if parent exists
            if parent_id and parent_id not in messages:
                report["warnings"].append(
                    f"Message {message_id} references non-existent parent {parent_id}"
                )
                orphaned_messages.append(message_id)

            # Track root messages
            if not parent_id:
                root_messages.append(message_id)

            # Validate parent's children list
            if parent_id and parent_id in messages:
                parent = messages[parent_id]
                if message_id not in parent.get("childrenIds", []):
                    if not self.valves.dry_run:
                        parent.setdefault("childrenIds", []).append(message_id)
                        report["repaired"] = True
                        report["repairedIssues"].append(
                            f"Added missing child reference {message_id} to parent {parent_id}"
                        )

        # Handle orphaned messages
        if orphaned_messages and root_messages and not self.valves.dry_run:
            primary_root = root_messages[0]
            for orphan_id in orphaned_messages:
                messages[orphan_id]["parentId"] = primary_root
                messages[primary_root].setdefault("childrenIds", []).append(orphan_id)
                report["repaired"] = True
                report["repairedIssues"].append(
                    f"Connected orphaned message {orphan_id} to root {primary_root}"
                )

        # Validate currentId
        if current_id and current_id not in messages:
            report["warnings"].append(
                f"Current ID {current_id} references non-existent message"
            )
            if root_messages and not self.valves.dry_run:
                history["currentId"] = root_messages[0]
                report["repaired"] = True
                report["repairedIssues"].append(
                    f"Reset currentId to {root_messages[0]}"
                )

        # Set overall validity
        report["isValid"] = len(report["errors"]) == 0
        return report

    async def check_chat_integrity(
        self,
        chat_id: Optional[str] = None,
        skip: Optional[int] = 0,
        __user__: Optional[dict] = None,
        __event_emitter__=None,
    ) -> str:
        """
        Check and repair chat structural integrity.

        :param chat_id: Specific chat ID to check (optional, if not provided checks all user chats)
        :param skip: Number of chats to skip for pagination (default: 0)
        :return: Summary report of the integrity check
        """

        try:
            from open_webui.models.chats import Chats

            # Set up logging (force=True prevents repeated config warnings)
            logging.basicConfig(
                level=getattr(logging, self.valves.log_level), force=True
            )

            # Get user valves
            user_valves = __user__.get("valves", {}) if __user__ else {}
            if hasattr(user_valves, "check_own_chats_only"):
                # It's a UserValves Pydantic model
                check_own_chats_only = user_valves.check_own_chats_only
            else:
                check_own_chats_only = user_valves.get("check_own_chats_only", True)

            if __event_emitter__:
                await __event_emitter__(
                    {
                        "type": "status",
                        "data": {
                            "description": "Initializing chat integrity check...",
                            "done": False,
                        },
                    }
                )

            # Get chats to process
            if chat_id:
                # Check specific chat
                chat = await Chats.get_chat_by_id(chat_id)  # ✅ ADDED await
                if not chat:
                    if __event_emitter__:
                        await __event_emitter__(
                            {
                                "type": "status",
                                "data": {
                                    "description": f"Chat {chat_id} not found",
                                    "done": True,
                                    "error": True,
                                },
                            }
                        )
                    return f"Chat {chat_id} not found"

                # Check if user has access to this chat
                if (
                    check_own_chats_only
                    and __user__
                    and chat.user_id != __user__.get("id")
                ):
                    if __event_emitter__:
                        await __event_emitter__(
                            {
                                "type": "status",
                                "data": {
                                    "description": "Access denied: You can only check your own chats",
                                    "done": True,
                                    "error": True,
                                },
                            }
                        )
                    return "Access denied: You can only check your own chats"

                all_chats = [chat]
            else:
                # Get user's chats or all chats based on user valves
                if check_own_chats_only and __user__:
                    all_chats = await Chats.get_chat_list_by_user_id(  # ✅ ADDED await
                        __user__.get("id"),
                        include_archived=True,
                        skip=skip,
                        limit=self.valves.max_chats_per_run,
                    )
                else:
                    all_chats = await Chats.get_chats(  # ✅ ADDED await
                        skip=skip, limit=self.valves.max_chats_per_run
                    )

            total_chats = len(all_chats)
            # Emit initial progress
            if __event_emitter__:
                await __event_emitter__(
                    {
                        "type": "status",
                        "data": {
                            "description": f"Found {total_chats} chats to process",
                            "progress": 0,
                            "total": total_chats,
                            "done": False,
                        },
                    }
                )

            results = {
                "total_chats": len(all_chats),
                "processed_chats": 0,
                "valid_chats": 0,
                "invalid_chats": 0,
                "repaired_chats": 0,
                "chat_reports": [],
            }

            self.logger.info(f"Starting chat integrity check on {len(all_chats)} chats")

            for i, chat in enumerate(all_chats):
                try:
                    # Emit progress for each chat
                    if __event_emitter__:
                        await __event_emitter__(
                            {
                                "type": "status",
                                "data": {
                                    "description": f"Processing chat: {getattr(chat, 'title', 'Unknown')[:50]}...",
                                    "progress": i + 1,
                                    "total": total_chats,
                                    "current_chat_id": chat.id,
                                    "done": False,
                                },
                            }
                        )

                    self.logger.info(
                        f"Processing chat ID: {chat.id} (Title: {getattr(chat, 'title', 'Unknown')})"
                    )

                    chat_data = chat.chat if hasattr(chat, "chat") else chat
                    report = self.validate_and_repair_chat(chat_data)

                    results["processed_chats"] += 1

                    if report["isValid"]:
                        results["valid_chats"] += 1
                        # Emit success for valid chat
                        if __event_emitter__:
                            await __event_emitter__(
                                {
                                    "type": "chat_result",
                                    "data": {
                                        "chat_id": chat.id,
                                        "status": "valid",
                                        "title": getattr(chat, "title", "Unknown"),
                                    },
                                }
                            )
                    else:
                        results["invalid_chats"] += 1
                        # Emit warning for invalid chat
                        if __event_emitter__:
                            await __event_emitter__(
                                {
                                    "type": "chat_result",
                                    "data": {
                                        "chat_id": chat.id,
                                        "status": "invalid",
                                        "title": getattr(chat, "title", "Unknown"),
                                        "errors": report["errors"],
                                    },
                                }
                            )

                    if report["repaired"]:
                        results["repaired_chats"] += 1
                        # Save repaired chat back to database
                        if not self.valves.dry_run:
                            await Chats.update_chat_by_id(
                                chat.id, chat_data
                            )  # ✅ ADDED await
                            self.logger.info(
                                f"Chat {chat.id} repaired: {', '.join(report['repairedIssues'])}"
                            )

                        # Emit repair notification
                        if __event_emitter__:
                            await __event_emitter__(
                                {
                                    "type": "chat_result",
                                    "data": {
                                        "chat_id": chat.id,
                                        "status": "repaired",
                                        "title": getattr(chat, "title", "Unknown"),
                                        "repairs": report["repairedIssues"],
                                    },
                                }
                            )

                    # Log issues
                    if report["errors"]:
                        self.logger.warning(
                            f"Chat {chat.id} has errors: {', '.join(report['errors'])}"
                        )
                    if report["warnings"]:
                        self.logger.debug(
                            f"Chat {chat.id} warnings: {', '.join(report['warnings'])}"
                        )

                    # Add detailed report for problematic chats
                    if report["errors"] or report["warnings"] or report["repaired"]:
                        results["chat_reports"].append(
                            {
                                "chat_id": chat.id,
                                "chat_title": getattr(chat, "title", "Unknown"),
                                "report": report,
                            }
                        )

                    # Emit periodic progress updates
                    if __event_emitter__ and (i + 1) % 5 == 0:
                        await __event_emitter__(
                            {
                                "type": "progress_update",
                                "data": {
                                    "processed": results["processed_chats"],
                                    "valid": results["valid_chats"],
                                    "invalid": results["invalid_chats"],
                                    "repaired": results["repaired_chats"],
                                    "progress": i + 1,
                                    "total": total_chats,
                                },
                            }
                        )

                except Exception as e:
                    self.logger.error(
                        f"Error processing chat {getattr(chat, 'id', 'unknown')}: {str(e)}"
                    )
                    results["chat_reports"].append(
                        {
                            "chat_id": getattr(chat, "id", "unknown"),
                            "error": f"Processing error: {str(e)}",
                        }
                    )
                    # Emit error for failed chat
                    if __event_emitter__:
                        await __event_emitter__(
                            {
                                "type": "chat_result",
                                "data": {
                                    "chat_id": getattr(chat, "id", "unknown"),
                                    "status": "error",
                                    "error": str(e),
                                },
                            }
                        )

            self.logger.info(
                f"Chat integrity check completed. Processed: {results['processed_chats']}, Valid: {results['valid_chats']}, Repaired: {results['repaired_chats']}"
            )

            # Final completion status
            if __event_emitter__:
                await __event_emitter__(
                    {
                        "type": "status",
                        "data": {
                            "description": "Chat integrity check completed!",
                            "progress": total_chats,
                            "total": total_chats,
                            "done": True,
                            "summary": {
                                "processed": results["processed_chats"],
                                "valid": results["valid_chats"],
                                "invalid": results["invalid_chats"],
                                "repaired": results["repaired_chats"],
                            },
                        },
                    }
                )

            # Generate summary
            summary = f"""Chat Integrity Check Complete!

Batch: {skip + 1} to {skip + len(all_chats)}
Total Chats: {results['total_chats']}
Processed: {results['processed_chats']}
Valid: {results['valid_chats']}
Invalid: {results['invalid_chats']}
Repaired: {results['repaired_chats']}

Mode: {'DRY RUN' if self.valves.dry_run else 'REPAIR MODE'}

Next batch command: check_chat_integrity(skip={skip + self.valves.max_chats_per_run})

{len(results['chat_reports'])} chats had issues or were repaired.

Detailed Reports:
"""

            for report in results["chat_reports"][
                :10
            ]:  # Show first 10 detailed reports
                if "error" in report:
                    summary += f"\n❌ Chat {report['chat_id']}: {report['error']}"
                else:
                    chat_report = report["report"]
                    status = "✅ Valid" if chat_report["isValid"] else "❌ Invalid"
                    if chat_report["repaired"]:
                        status += " (Repaired)"
                    summary += (
                        f"\n{status} Chat {report['chat_id']} ({report['chat_title']})"
                    )

                    if chat_report["errors"]:
                        summary += f"\n  Errors: {', '.join(chat_report['errors'])}"
                    if chat_report["warnings"]:
                        summary += f"\n  Warnings: {', '.join(chat_report['warnings'])}"
                    if chat_report["repairedIssues"]:
                        summary += (
                            f"\n  Repairs: {', '.join(chat_report['repairedIssues'])}"
                        )

            if len(results["chat_reports"]) > 10:
                summary += f"\n... and {len(results['chat_reports']) - 10} more chats with issues"

            return summary

        except Exception as e:
            error_msg = f"Error during chat integrity check: {str(e)}"
            self.logger.error(error_msg)
            if __event_emitter__:
                await __event_emitter__(
                    {
                        "type": "status",
                        "data": {
                            "description": f"Error: {error_msg}",
                            "done": True,
                            "error": True,
                        },
                    }
                )
            return error_msg
<!-- gh-comment-id:4331257958 --> @ghost commented on GitHub (Apr 27, 2026): ``` from __future__ import annotations from pydantic import BaseModel, Field from typing import Optional, Dict, List, Any, Literal import json import logging class Tools: class Valves(BaseModel): dry_run: bool = Field( default=True, description="If true, only report issues without fixing them." ) max_chats_per_run: int = Field( default=50, description="Maximum number of chats to process in one run." ) log_level: Literal["DEBUG", "INFO", "WARNING", "ERROR"] = Field( default="INFO", description="Logging level for the function operations." ) class UserValves(BaseModel): check_own_chats_only: bool = Field( default=True, description="If true, only check chats owned by the current user.", ) dry_run: bool = Field( default=True, description="If true, only report issues without fixing them." ) max_chats_per_run: int = Field( default=50, description="Maximum number of chats to process in one run." ) log_level: Literal["DEBUG", "INFO", "WARNING", "ERROR"] = Field( default="INFO", description="Logging level for the function operations." ) def __init__(self): self.valves = self.Valves() self.logger = logging.getLogger(__name__) def validate_and_repair_chat(self, chat_data: Dict[str, Any]) -> Dict[str, Any]: """Validate and repair a single chat's structural integrity.""" report = { "isValid": True, "errors": [], "warnings": [], "repaired": False, "repairedIssues": [], } # Check if chat has required structure if not chat_data or not isinstance(chat_data, dict): report["errors"].append("Chat object is null or not a dictionary") report["isValid"] = False return report # Validate history structure history = chat_data.get("history", {}) if not isinstance(history, dict): report["errors"].append("Chat history is missing or invalid") report["isValid"] = False return report messages = history.get("messages", {}) current_id = history.get("currentId") if not isinstance(messages, dict): report["errors"].append("Messages object is missing or invalid") report["isValid"] = False return report message_ids = list(messages.keys()) if len(message_ids) == 0: report["warnings"].append("Chat has no messages") return report # Track relationships for repair orphaned_messages = [] invalid_messages = [] root_messages = [] # First pass: validate individual messages for message_id in message_ids: message = messages[message_id] if not isinstance(message, dict): report["errors"].append(f"Message {message_id} is not a dictionary") invalid_messages.append(message_id) continue # Check required fields if not message.get("id") or message["id"] != message_id: if message.get("id") and message["id"] != message_id: report["warnings"].append( f"Message ID mismatch: key={message_id}, id={message.get('id')}" ) if not self.valves.dry_run: message["id"] = message_id report["repaired"] = True report["repairedIssues"].append( f"Fixed ID mismatch for message {message_id}" ) else: if not self.valves.dry_run: message["id"] = message_id report["repaired"] = True report["repairedIssues"].append( f"Added missing ID for message {message_id}" ) # Validate content if not isinstance(message.get("content"), str): if message.get("content") is None: if not self.valves.dry_run: message["content"] = "" report["repaired"] = True report["repairedIssues"].append( f"Fixed null content for message {message_id}" ) else: report["errors"].append( f"Message {message_id} has invalid content type" ) invalid_messages.append(message_id) continue # Validate role if message.get("role") not in ["user", "assistant", "system"]: report["errors"].append( f"Message {message_id} has invalid role: {message.get('role')}" ) invalid_messages.append(message_id) continue # Initialize childrenIds if missing if not isinstance(message.get("childrenIds"), list): if not self.valves.dry_run: message["childrenIds"] = [] report["repaired"] = True report["repairedIssues"].append( f"Fixed missing childrenIds for message {message_id}" ) # Remove invalid messages (if not dry run) if not self.valves.dry_run: for invalid_id in invalid_messages: del messages[invalid_id] report["repaired"] = True report["repairedIssues"].append(f"Removed invalid message {invalid_id}") # Second pass: validate parent-child relationships valid_message_ids = [mid for mid in message_ids if mid not in invalid_messages] for message_id in valid_message_ids: message = messages[message_id] parent_id = message.get("parentId") # Check if parent exists if parent_id and parent_id not in messages: report["warnings"].append( f"Message {message_id} references non-existent parent {parent_id}" ) orphaned_messages.append(message_id) # Track root messages if not parent_id: root_messages.append(message_id) # Validate parent's children list if parent_id and parent_id in messages: parent = messages[parent_id] if message_id not in parent.get("childrenIds", []): if not self.valves.dry_run: parent.setdefault("childrenIds", []).append(message_id) report["repaired"] = True report["repairedIssues"].append( f"Added missing child reference {message_id} to parent {parent_id}" ) # Handle orphaned messages if orphaned_messages and root_messages and not self.valves.dry_run: primary_root = root_messages[0] for orphan_id in orphaned_messages: messages[orphan_id]["parentId"] = primary_root messages[primary_root].setdefault("childrenIds", []).append(orphan_id) report["repaired"] = True report["repairedIssues"].append( f"Connected orphaned message {orphan_id} to root {primary_root}" ) # Validate currentId if current_id and current_id not in messages: report["warnings"].append( f"Current ID {current_id} references non-existent message" ) if root_messages and not self.valves.dry_run: history["currentId"] = root_messages[0] report["repaired"] = True report["repairedIssues"].append( f"Reset currentId to {root_messages[0]}" ) # Set overall validity report["isValid"] = len(report["errors"]) == 0 return report async def check_chat_integrity( self, chat_id: Optional[str] = None, skip: Optional[int] = 0, __user__: Optional[dict] = None, __event_emitter__=None, ) -> str: """ Check and repair chat structural integrity. :param chat_id: Specific chat ID to check (optional, if not provided checks all user chats) :param skip: Number of chats to skip for pagination (default: 0) :return: Summary report of the integrity check """ try: from open_webui.models.chats import Chats # Set up logging (force=True prevents repeated config warnings) logging.basicConfig( level=getattr(logging, self.valves.log_level), force=True ) # Get user valves user_valves = __user__.get("valves", {}) if __user__ else {} if hasattr(user_valves, "check_own_chats_only"): # It's a UserValves Pydantic model check_own_chats_only = user_valves.check_own_chats_only else: check_own_chats_only = user_valves.get("check_own_chats_only", True) if __event_emitter__: await __event_emitter__( { "type": "status", "data": { "description": "Initializing chat integrity check...", "done": False, }, } ) # Get chats to process if chat_id: # Check specific chat chat = await Chats.get_chat_by_id(chat_id) # ✅ ADDED await if not chat: if __event_emitter__: await __event_emitter__( { "type": "status", "data": { "description": f"Chat {chat_id} not found", "done": True, "error": True, }, } ) return f"Chat {chat_id} not found" # Check if user has access to this chat if ( check_own_chats_only and __user__ and chat.user_id != __user__.get("id") ): if __event_emitter__: await __event_emitter__( { "type": "status", "data": { "description": "Access denied: You can only check your own chats", "done": True, "error": True, }, } ) return "Access denied: You can only check your own chats" all_chats = [chat] else: # Get user's chats or all chats based on user valves if check_own_chats_only and __user__: all_chats = await Chats.get_chat_list_by_user_id( # ✅ ADDED await __user__.get("id"), include_archived=True, skip=skip, limit=self.valves.max_chats_per_run, ) else: all_chats = await Chats.get_chats( # ✅ ADDED await skip=skip, limit=self.valves.max_chats_per_run ) total_chats = len(all_chats) # Emit initial progress if __event_emitter__: await __event_emitter__( { "type": "status", "data": { "description": f"Found {total_chats} chats to process", "progress": 0, "total": total_chats, "done": False, }, } ) results = { "total_chats": len(all_chats), "processed_chats": 0, "valid_chats": 0, "invalid_chats": 0, "repaired_chats": 0, "chat_reports": [], } self.logger.info(f"Starting chat integrity check on {len(all_chats)} chats") for i, chat in enumerate(all_chats): try: # Emit progress for each chat if __event_emitter__: await __event_emitter__( { "type": "status", "data": { "description": f"Processing chat: {getattr(chat, 'title', 'Unknown')[:50]}...", "progress": i + 1, "total": total_chats, "current_chat_id": chat.id, "done": False, }, } ) self.logger.info( f"Processing chat ID: {chat.id} (Title: {getattr(chat, 'title', 'Unknown')})" ) chat_data = chat.chat if hasattr(chat, "chat") else chat report = self.validate_and_repair_chat(chat_data) results["processed_chats"] += 1 if report["isValid"]: results["valid_chats"] += 1 # Emit success for valid chat if __event_emitter__: await __event_emitter__( { "type": "chat_result", "data": { "chat_id": chat.id, "status": "valid", "title": getattr(chat, "title", "Unknown"), }, } ) else: results["invalid_chats"] += 1 # Emit warning for invalid chat if __event_emitter__: await __event_emitter__( { "type": "chat_result", "data": { "chat_id": chat.id, "status": "invalid", "title": getattr(chat, "title", "Unknown"), "errors": report["errors"], }, } ) if report["repaired"]: results["repaired_chats"] += 1 # Save repaired chat back to database if not self.valves.dry_run: await Chats.update_chat_by_id( chat.id, chat_data ) # ✅ ADDED await self.logger.info( f"Chat {chat.id} repaired: {', '.join(report['repairedIssues'])}" ) # Emit repair notification if __event_emitter__: await __event_emitter__( { "type": "chat_result", "data": { "chat_id": chat.id, "status": "repaired", "title": getattr(chat, "title", "Unknown"), "repairs": report["repairedIssues"], }, } ) # Log issues if report["errors"]: self.logger.warning( f"Chat {chat.id} has errors: {', '.join(report['errors'])}" ) if report["warnings"]: self.logger.debug( f"Chat {chat.id} warnings: {', '.join(report['warnings'])}" ) # Add detailed report for problematic chats if report["errors"] or report["warnings"] or report["repaired"]: results["chat_reports"].append( { "chat_id": chat.id, "chat_title": getattr(chat, "title", "Unknown"), "report": report, } ) # Emit periodic progress updates if __event_emitter__ and (i + 1) % 5 == 0: await __event_emitter__( { "type": "progress_update", "data": { "processed": results["processed_chats"], "valid": results["valid_chats"], "invalid": results["invalid_chats"], "repaired": results["repaired_chats"], "progress": i + 1, "total": total_chats, }, } ) except Exception as e: self.logger.error( f"Error processing chat {getattr(chat, 'id', 'unknown')}: {str(e)}" ) results["chat_reports"].append( { "chat_id": getattr(chat, "id", "unknown"), "error": f"Processing error: {str(e)}", } ) # Emit error for failed chat if __event_emitter__: await __event_emitter__( { "type": "chat_result", "data": { "chat_id": getattr(chat, "id", "unknown"), "status": "error", "error": str(e), }, } ) self.logger.info( f"Chat integrity check completed. Processed: {results['processed_chats']}, Valid: {results['valid_chats']}, Repaired: {results['repaired_chats']}" ) # Final completion status if __event_emitter__: await __event_emitter__( { "type": "status", "data": { "description": "Chat integrity check completed!", "progress": total_chats, "total": total_chats, "done": True, "summary": { "processed": results["processed_chats"], "valid": results["valid_chats"], "invalid": results["invalid_chats"], "repaired": results["repaired_chats"], }, }, } ) # Generate summary summary = f"""Chat Integrity Check Complete! Batch: {skip + 1} to {skip + len(all_chats)} Total Chats: {results['total_chats']} Processed: {results['processed_chats']} Valid: {results['valid_chats']} Invalid: {results['invalid_chats']} Repaired: {results['repaired_chats']} Mode: {'DRY RUN' if self.valves.dry_run else 'REPAIR MODE'} Next batch command: check_chat_integrity(skip={skip + self.valves.max_chats_per_run}) {len(results['chat_reports'])} chats had issues or were repaired. Detailed Reports: """ for report in results["chat_reports"][ :10 ]: # Show first 10 detailed reports if "error" in report: summary += f"\n❌ Chat {report['chat_id']}: {report['error']}" else: chat_report = report["report"] status = "✅ Valid" if chat_report["isValid"] else "❌ Invalid" if chat_report["repaired"]: status += " (Repaired)" summary += ( f"\n{status} Chat {report['chat_id']} ({report['chat_title']})" ) if chat_report["errors"]: summary += f"\n Errors: {', '.join(chat_report['errors'])}" if chat_report["warnings"]: summary += f"\n Warnings: {', '.join(chat_report['warnings'])}" if chat_report["repairedIssues"]: summary += ( f"\n Repairs: {', '.join(chat_report['repairedIssues'])}" ) if len(results["chat_reports"]) > 10: summary += f"\n... and {len(results['chat_reports']) - 10} more chats with issues" return summary except Exception as e: error_msg = f"Error during chat integrity check: {str(e)}" self.logger.error(error_msg) if __event_emitter__: await __event_emitter__( { "type": "status", "data": { "description": f"Error: {error_msg}", "done": True, "error": True, }, } ) return error_msg ```
Author
Owner

@rgaricano commented on GitHub (Apr 29, 2026):

Image

how is this .py extension supposed to be imported as function if its not in json format even?

@rgaricano

copy-paste

<!-- gh-comment-id:4347219053 --> @rgaricano commented on GitHub (Apr 29, 2026): > <img width="692" height="236" alt="Image" src="https://github.com/user-attachments/assets/83015f86-e2e4-46e1-8d8a-ed5a26b16f8d" /> > > how is this .py extension supposed to be imported as function if its not in json format even? > > @rgaricano copy-paste
Author
Owner

@rgaricano commented on GitHub (Apr 29, 2026):

{"error":"Error during chat integrity check: object of type 'coroutine' has no len()"}

yes, because it need to be refact to work with changes of openwebui >= v0.9.0 (add some await in functions calls).
I don't know when, or if, I'm going to do it, feel free to change it. by the way...@silentoplayz did some impro: https://openwebui.com/posts/chat_integrity_checker_repair_fd3f34ba

<!-- gh-comment-id:4347324877 --> @rgaricano commented on GitHub (Apr 29, 2026): > {"error":"Error during chat integrity check: object of type 'coroutine' has no len()"} yes, because it need to be refact to work with changes of openwebui >= v0.9.0 (add some `await` in functions calls). I don't know when, or if, I'm going to do it, feel free to change it. by the way...@silentoplayz did some impro: https://openwebui.com/posts/chat_integrity_checker_repair_fd3f34ba
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/open-webui#56159