Skip to content

[Bug] Responses WebSocket 在 CONNECTING 阶段取消会触发 uncaughtException 并重启 app #1330

Description

@i-square

问题描述

启用 OpenAI Responses WebSocket 后,如果客户端请求在上游 WebSocket 尚处于 CONNECTING
状态时取消,app 可能抛出以下未捕获异常并退出:

Error: WebSocket was closed before the connection was established
[Lifecycle] uncaughtException

在使用 restart: unless-stopped 的 Docker Compose 部署中,进程退出会被自动拉起,表现为:

  • app 运行时长频繁重置。
  • 正在进行的流式请求全部中断。
  • 前端短时间不可访问。
  • 容器没有 OOM,PostgreSQL 和 Redis 仍然健康。

一次实际运行中,同一容器在数小时内因此自动重启 11 次,所有 fatal 日志均为同一个异常。

复现条件

  1. 系统设置 enableOpenaiResponsesWebsocket=true
  2. 客户端通过 WebSocket 请求 /v1/responses
  3. 选中 Codex 类型 Provider。
  4. 上游 WebSocket 尚未完成握手时,客户端断开或 AbortSignal 被触发。

根因分析

src/app/v1/_lib/responses-ws/upstream-adapter.ts 中:

  1. onAbort() 调用 finishRequest({ closeCode: 1000, forgetSession: true })
  2. finishRequest() 首先调用 cleanupRequestListeners(),移除 error 监听器。
  3. 随后通过 closeAndForget() 调用 ws.close(code)
  4. 当 socket 仍为 CONNECTING 时,ws 会异步发出
    WebSocket was closed before the connection was established 错误。
  5. 因为请求级 error 监听已经移除,错误逃逸到进程级 uncaughtException
  6. src/instrumentation.ts 的崩溃处理器执行 process.exit(1),Docker 随后重启 app。

这是请求级取消事件被放大为整个服务重启的问题。

期望行为

  • 请求在 WebSocket 握手阶段取消时,只终止该请求和对应上游 socket。
  • 不产生进程级 uncaughtExceptionunhandledRejection
  • app 不退出、不重启,其他请求不受影响。
  • 禁用上游 Responses WebSocket 时,应继续通过 HTTP Responses 正常转发。

当前配置局限

当前开关仅存储在数据库字段:

system_settings.enable_openai_responses_websocket

代码中没有对应环境变量。系统设置表单虽然读取并保存
enableOpenaiResponsesWebsocket,但当前 JSX 没有渲染该 Switch,因此部分版本的管理页面无法关闭它。

直接修改数据库可以临时关闭功能,但不利于不可变镜像部署、灾难恢复和后续版本升级。

建议的环境变量接口

增加一个可选的三态覆盖变量:

# 未设置:继续读取数据库系统设置,保持现有行为。
# false:强制禁用上游 OpenAI Responses WebSocket。
# true:强制启用上游 OpenAI Responses WebSocket。
ENABLE_OPENAI_RESPONSES_WEBSOCKET=false

优先级建议:

有效环境变量覆盖值 > 数据库系统设置 > 当前默认值

必须采用“未设置时读取数据库”的三态语义,不能把默认环境变量值设为 false,否则会静默改变现有部署。

本地部署可以立即使用:

ENABLE_OPENAI_RESPONSES_WEBSOCKET=false

Compose 已通过 env_file: ./.env 注入变量,不需要数据库迁移,也不需要修改 Compose 的
environment 列表。

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:OpenAIbugSomething isn't workingoncallCritical blocking issue requiring immediate oncall attention

    Projects

    Status
    Done

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions