快速结论:该报错通常出现在 Open WebUI 聊天记录中查看历史 Open Terminal 文件卡片(如 XLSX、DOCX)时,若当前 composer 没有选中卡片所属的终端,卡片就会显示 Terminal unavailable;优先排查卡片关联的 terminal 是否仍在当前用户可访问的终端列表中,以及前端是否错误地依赖了 composer 的当前选择。
适用环境:Open WebUI v0.11.3(当前 dev 也受影响);Docker 安装;Linux;Chrome 149。Issue 明确涉及系统级 Open Terminal(system-level terminal),不涉及 direct-terminal URL 问题。
最快修复方案:暂无确认的一步修复方案。Issue 最终被报告者自行关闭,关闭原因是修正复现后无法在未修改的 v0.11.3 上复现同用户行为;因此没有已验证的代码级修复步骤。
注意事项:报告者最初观察到的失败实际发生在管理员通过 /s/<chat-id> 路由查看其他用户聊天时,而不是终端工作区所有者在正常 /c/... 聊天中查看自己的对话。Open Terminal 多用户工作区按用户隔离,跨用户访问的“不可用”可能属于预期隔离行为,而不一定是同用户场景下的 bug。
问题场景
用户在 Open WebUI 的聊天记录中查看此前由 Open Terminal 生成的文件卡片,例如 XLSX 或 DOCX 预览卡片。复现路径是:先选中一个系统 Open Terminal 连接,在聊天中创建并显示文件,确认卡片能正常渲染;然后清除 localStorage.selectedTerminalId 并重新加载聊天;此时历史卡片显示 Terminal unavailable。再次选中同一个终端后,卡片无需重新创建文件即可立即渲染。
Issue 正文认为问题出在前端组件 src/lib/components/chat/Messages/TerminalOutputFile.svelte 中的选择检查逻辑:历史卡片本应根据自身保存的 terminal_selector 解析终端,而不是依赖 composer 当前选中的终端。
报错原文
Terminal unavailable
Issue 中引用的前端 guard 代码:
if (!selector || $selectedTerminalId !== selector) return null;
Issue 还指出,仅移除选择检查并不足够,因为:
$: terminal = resolveTerminal();
没有响应式依赖,只会在挂载时解析一次。如果此时 $terminalServers 仍为 null,卡片会一直不可用。terminal 需要依赖 selector、$terminalServers 和 $settings。
此外,direct terminal 仍与选择绑定:Chat.svelte 只为当前选中的 direct terminal 设置 enabled,而查找逻辑要求 server.enabled。不过本 Issue 报告的是 system terminal,不涉及 direct terminal。
原因分析
可能原因一:历史文件卡片渲染时错误地要求 composer 当前选中的终端与卡片保存的 terminal_selector 一致。当 composer 没有选择终端,或选择被清除后,guard 在发起任何请求之前就返回 null,导致卡片显示 Terminal unavailable。Issue 中提到,正常工作的卡片会通过 /api/v1/terminals/<terminal-id>/files/view 请求文件;而 composer 选择为空时,guard 在请求之前就返回了。
可能原因二:即使移除选择检查,resolveTerminal() 也只会在挂载时解析一次;如果当时 $terminalServers 仍为 null,卡片仍然无法解析终端。Issue 认为需要让 terminal 依赖 selector、$terminalServers 和 $settings。
需要注意:Issue 最终由报告者关闭,原因是修正复现后发现,最初观察到的失败发生在管理员通过 /s/<chat-id> 查看其他用户聊天时,而非终端工作区所有者在正常 /c/... 聊天中的同用户场景。报告者在未修改的 v0.11.3 上重新测试所属账号后,XLSX 预览在刷新后可以正常渲染,因此无法复现同用户行为。该问题是否确实存在于同用户场景,尚未在 Issue 中确认。
环境排查
- Open WebUI 版本:确认是否为 v0.11.3 或当前 dev;Issue 表示当前 dev 也受影响。
- 安装方式:确认是否为 Docker 安装。
- 操作系统:确认是否为 Linux。
- 浏览器:确认是否为 Chrome 149,或是否存在浏览器扩展干扰。
- 终端类型:确认使用的是系统级 Open Terminal,还是 direct terminal。Issue 明确指出本报告覆盖 system terminal,不涉及 #27621 的 direct-terminal URL 问题。
- 用户与路由:确认当前查看聊天的是终端工作区所有者本人,还是管理员通过
/s/<chat-id>查看其他用户的聊天。Issue 关闭时指出,跨用户查看时 Open Terminal 多用户工作区按用户隔离。 - 前端状态:检查
localStorage.selectedTerminalId是否为空,以及 composer 当前选中的终端是否与卡片保存的终端一致。 - 组件逻辑:检查
src/lib/components/chat/Messages/TerminalOutputFile.svelte中是否存在if (!selector || $selectedTerminalId !== selector) return null;这一 guard,以及resolveTerminal()是否具有响应式依赖。
解决步骤
- 先确认复现场景是否属于同用户场景。使用终端工作区所有者账号,在正常
/c/...聊天中打开历史文件卡片,而不是使用管理员通过/s/<chat-id>查看其他用户聊天。Issue 关闭时明确指出,跨用户查看时 Open Terminal 多用户工作区按用户隔离,原报告者无法在同用户、未修改的 v0.11.3 上复现。 - 如果确实只在跨用户查看时出现
Terminal unavailable,不要将其视为同用户历史卡片 bug;这可能是多用户隔离带来的预期行为。可优先尝试用所属账号在正常聊天路由中验证。 - 如果同用户场景也能稳定复现,先记录当前
localStorage.selectedTerminalId的值,并清除后重新加载聊天,确认卡片是否仍然显示Terminal unavailable。 - 再次选中卡片所属的终端,确认卡片是否立即恢复渲染。Issue 提到,选中同一个终端后,卡片无需重新创建文件即可渲染。
- 检查
TerminalOutputFile.svelte中的 guard。Issue 指出当前 dev 含有if (!selector || $selectedTerminalId !== selector) return null;,该逻辑会在 composer 未选中终端时提前返回。 - 不要只删除选择检查。Issue 明确说明仅移除选择检查不够:
$: terminal = resolveTerminal();没有响应式依赖,若挂载时$terminalServers仍为null,卡片仍可能不可用。需要考虑让terminal依赖selector、$terminalServers和$settings。 - 如果使用 direct terminal,请注意
Chat.svelte只为当前选中的 direct terminal 设置enabled,查找逻辑要求server.enabled;本 Issue 不覆盖 direct terminal 的修复。
验证方法
使用终端工作区所有者账号,在正常 /c/... 聊天中打开包含历史 XLSX 或 DOCX 文件卡片的对话。清除 localStorage.selectedTerminalId 并重新加载页面,观察卡片是否仍显示 Terminal unavailable。如果卡片能够在不依赖 composer 当前选择的情况下正常渲染,说明同用户场景下的问题已解决。若只在管理员通过 /s/<chat-id> 查看其他用户聊天时出现,则更可能是多用户隔离行为,而不是同用户历史卡片渲染 bug。
参考来源
AI 工具推荐
想把多个 AI 模型放在一个入口?
GamsGo AI 集成 ChatGPT、DeepSeek、Gemini、Claude、Midjourney、Veo 等常用模型,适合写作、绘图、视频和日常 AI 工作流。
推广链接:通过此链接购买,我可能获得佣金,不影响你的价格。
这个方案解决了吗?
可以继续搜索完整报错,或查看同一工具的其他排查指南。


