You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
摘要
对一个规范日志较大的会话执行"分叉(fork / seeded session)"后,新会话里任何请求都会失败,包括
/compact:而且不会自愈:不是偶发,而是每次请求都必然失败。
根因:默认开启的
session-log-deepseek会随每个官方 API 请求上传"上次被服务端接收之后的规范会话日志"。分叉会话的"已接收水位"永远是-1(下面有测量方法),于是第一个请求就把继承来的整份日志塞进请求体(实测 48.8 MiB),超过上游网关约 50 MB 的 body 上限被拒;又因为 413 归类为不可重试、且非 2xx 不写接收水位,水位永远不推进 ⇒ 每个后续请求重传同一份 48.8 MiB ⇒ 永久死锁。环境
dsh-v0.1.6-alpha.1(commit0a15e36e7f);master上相关代码仍在(2026-09-20 核对)deepseek-official/deepseek-flash,Anthropic Messages 兼容端点https://api.deepseek.com/anthropic/v1/messagesisSeeded: true,parentSession指向父会话),父子都在本机复现
/compact→ 同样 413。期望:分叉会话可以正常工作(哪怕退化成"这一轮不带日志字段"或"分片上传")。
实际:永久失败,而且错误信息完全看不出原因。
关键证据
1) 分叉会话的已接收水位恒为
-1水位由
acceptedThrough(session)折叠日志中的session-log-deepseek/delivery-accepted事件得到,且要求data.sessionId === session.id(packages/session/session-log-deepseek/src/index.ts:146)。测量方式(注意
session.v3.jsonl.zstd是多帧 zstd,逐帧解压才能拿到完整 JSONL):delivery-accepted,全部写的是父/祖父会话 id,写它自己的一条都没有 ⇒ 水位 =-1。2) 首个请求的载荷 ≈ 48.8 MiB
按 wire 结构累加分叉会话全部 15,121 条事件 ≈ 48.8 MiB,再加约 3 MB 模型输入 ≈ 52 MB。
3) 上游 body 上限约 50 MB(十进制)/ ≈47.7 MiB
直接对同一端点做体量探针(无模型输入,仅 body 大小):
Failed to buffer the request body: length limit exceeded(text/plain)Request Entity Too Large(openresty,text/html)再用该 fork 的真实日志内容作为
dsh_session_log字段复现:字段 40 MiB(体 44.2 MiB)→ 200;字段 47 MiB(体 51.8 MiB)→ 413。4) 失败闭环
packages/llm/llm-deepseek/src/protocols/messages/transport.ts:33:HTTP 413 ⇒ 归类INVALID_REQUEST,不可重试。delivery-accepted⇒ 水位保持-1。/compact也是带 live sessionId 的请求 ⇒ 携带同一个超大字段 ⇒ 同样 413(日志中两次 compact 尝试均以同样错误结束)。根因
session-log-deepseek的prepare()每次都把afterSeq + 1 .. throughSeq的完整后缀塞进dsh_session_log,没有任何字节上限。README 的 Known Limitations 自己也写了:叠加 fork 语义(README:37:"Forked sessions ignore inherited parent watermarks")后,结果就是:日志大的会话一旦分叉,新会话一出生就不可用,且没有任何用户侧恢复手段(连压缩都失败)。
另外,错误面也不友好:网关的 413 响应不是 JSON,
providerError()只能回落到DeepSeek Messages request failed (413),用户完全看不出是"日志字段太大"。我们认为这不是使用姿势问题:该组合结果本可以优雅降级,却没有降级。
建议修法(低风险、不丢数据)
afterSeq + 1 .. throughSeq)。给字段设一个安全上限(例如 32 MiB,远低于 ~47.7 MiB 的网关上限),throughSeq取实际包含的最后一条事件。水位会随着每次成功请求逐步推进:既不丢数据,也不会死锁。seedLength之前的事件已有可核验的接收记录,则从seedLength - 1起算,避免把几十 MB 重复上传一遍。INVALID_REQUEST。临时绕过
~/.dsh/profiles/<profile>/cordis.patch.yml):然后重启 dsh ⇒ 请求体回到约 3 MB,分叉会话立刻可用。代价是全局不再上传会话日志。
All reactions