快速结论:该报错发生在 Open WebUI 的笔记(Notes)协作编辑场景中。当服务端 Yjs 状态为空(例如重启后或笔记由非协作方式创建)但数据库中已有内容时,一次不含 data 的更新会取消待执行的保存任务却没有重新调度保存,导致编辑内容丢失。优先检查 Open WebUI 是否使用了 Redis 作为 WebSocket 管理器,以及服务端 Yjs 内存状态是否被重启清空。
适用环境:Open WebUI v0.11.0(Docker Compose 部署,Postgres 16 后端,未配置 Redis,WEBSOCKET_MANAGER 未设置,ENABLE_WEBSOCKET_SUPPORT 使用默认值)。Issue 作者在 Debian 12 宿主机上通过 Docker Compose 复现。
最快修复方案:暂无已确认的一步修复方案。Issue 中提到了触发条件,但未给出已验证的代码修复或配置变更。可优先尝试为 Open WebUI 配置 Redis,将 Yjs 更新日志从进程内存迁移到独立存储,避免服务重启导致 Yjs 历史丢失。
注意事项:该方案仅为推测,未被 Issue 作者验证。此外,即使配置 Redis,对于“笔记由非协作方式创建(如 write_note 工具或直接 POST)后首次打开”的场景,仍可能存在 Yjs 状态为空导致保存丢失的问题,需要配合其他修复措施。
问题场景
用户在使用 Open WebUI 的笔记编辑器时,输入的文字不会保存到数据库。编辑器界面始终显示完整文本,但数据库中的 note.data.content 仍是旧版本。只有继续输入一个字符,之前所有文字才会被写入数据库。等待、离开输入框或切换页面均无法触发保存。该问题在 Open WebUI v0.11.0 版本中复现。
报错原文
issue: note edits are lost when an update without a content snapshot cancels the pending save
该问题不产生具体的错误日志——保存操作从未被尝试执行,因此没有报错信息。Issue 作者明确指出“That silence is part of the problem”(这种静默本身就是问题的一部分)。
原因分析
问题出在 backend/open_webui/socket/main.py 的 yjs_document_update 函数中。待保存任务的取消和新任务的调度处于不同的条件分支下:
stop_item_tasks(REDIS, document_id)始终执行,用于取消待保存任务;- 而
create_task(REDIS, debounced_save(), document_id)仅在data.get('data')为真时才会执行。
当一次更新不携带 data 字段时(即“无内容快照”的更新),待保存任务被取消,却没有新的保存任务顶替,导致本次编辑内容永远不会写入数据库。
向服务器发送无 data 更新的代码路径来自 SocketIOCollaborationProvider(src/lib/components/common/RichTextInput/Collaboration.ts)中的 ydoc:document:state 处理器:当服务端报告 Yjs 文档状态为空、但编辑器已持有内容时,它会发出只含 update 字段(无 data)的 ydoc:document:update 消息。
这意味着以下场景容易触发:
- 非协作方式创建的笔记:由
write_note内置工具或直接调用POST /api/v1/notes/create创建的笔记没有任何 Yjs 历史记录(相关问题见 #28539)。 - 服务重启后:未配置 Redis 时,
YdocManager将更新日志保存在进程内存(self._updates = {})。每次重启 Open WebUI,所有笔记的 Yjs 历史都会丢失,而 Postgres 中的note.data.content仍然存在。下次打开任何有内容的笔记时,服务端会报告空状态,触发上述无data更新分支。
此外,NoteEditor.svelte 没有在卸载时(onDestroy)执行保存操作,其 REST 防抖保存仅提交 title、data.files 和 access_grants,从不提交 data.content。Yjs 路径是笔记文本的唯一写入通道,因此一旦保存被取消且无替补,数据就会丢失。
环境排查
- 确认 Open WebUI 版本是否为 v0.11.0 或更新(Issue 作者确认
dev分支代码路径未变)。 - 检查是否配置了 Redis(
WEBSOCKET_MANAGER环境变量)。未配置时REDIS为None,Yjs 更新日志仅存于进程内存。 - 确认 Postgres 版本(Issue 中为 16)。
- 确认部署方式是否为 Docker Compose 及镜像标签(
ghcr.io/open-webui/open-webui:v0.11.0)。 - 检查笔记是否由协作编辑器之外的方式创建(如
write_note工具、API 调用),此类笔记没有 Yjs 历史。 - 确认 Open WebUI 最近是否发生过重启(导致内存中 Yjs 历史被清空)。
解决步骤
- 首选为 Open WebUI 配置 Redis(设置
WEBSOCKET_MANAGER环境变量),使YdocManager的更新日志不再依赖进程内存,从而避免服务重启导致全部 Yjs 历史丢失。这是针对“重启导致空状态”触发条件的可能解决方案。 - 如配置 Redis 后问题仍存在,或笔记由非协作方式创建,需要从代码层面修复
yjs_document_update的逻辑——将保存任务调度移出data.get('data')条件,确保即使更新不带data,也会重新调度一个保存任务以承接被取消的任务。 - 作为临时规避手段(未经 Issue 验证):在每次输入后,通过 UI 强制触发一次带
data的保存,或在编辑后手动创建一个新的更新来触发保存链路。 - 跟踪相关 Issue(#28539、#26140、#25916)或上游修复进展,等待官方补丁。
验证方法
按以下步骤确认问题是否复现或已解决:
- 创建一个新的笔记,输入一段文字,等待防抖保存完成后离开笔记页面。
- 重启 Open WebUI(或模拟服务端 Yjs 状态清空),重新打开该笔记,确认编辑器中的内容与数据库一致。
- 在服务重启后立即编辑该笔记(不输入新字符),等待数秒后检查数据库中
note.data.content是否仍为旧内容——若为旧内容则问题复现。 - 若已应用修复,在同样操作下,编辑后的文字应自动写入数据库,无需额外输入字符触发。
参考来源
AI 工具推荐
想把多个 AI 模型放在一个入口?
GamsGo AI 集成 ChatGPT、DeepSeek、Gemini、Claude、Midjourney、Veo 等常用模型,适合写作、绘图、视频和日常 AI 工作流。
推广链接:通过此链接购买,我可能获得佣金,不影响你的价格。
这个方案解决了吗?
可以继续搜索完整报错,或查看同一工具的其他排查指南。


