## 现象 `nats/client.go:275/300/314/383` 的 Subscribe / SubscribeJSON / QueueSubscribeJSON / Reply 全部把用户 handler 原样透传给上游 SDK: ```go // client.go:300 func SubscribeJSON[T any](c *Client, subject string, handler func(ctx context.Context, msg *T)) (*nats.Subscription, error) { return c.Subscribe(subject, func(m *nats.Msg) { ... handler(extractTraceCtx(m), &payload) }) } ``` 而 nats.go v1.55.0 的异步派发循环直接调用、无任何 recover(`nats.go@v1.55.0/nats.go:3861`:`mcb(m)`,全文件的 recover 只用于 closeStatusListener)。同仓明文约定 `AGENTS.md:31`「禁止裸 `go func`:用 `github.com/oekit/concurrency/async` 的 GoSafe 系列(panic 被 recover)」,且 `wsutil/outbox.go:108` 写着「写协程 panic 只许死这条连接,不许死整个进程」——唯独接收**外部不可信载荷**的订阅 handler 没有这层隔离。 探针复现(`/tmp/pbprobe`,内嵌 nats-server,handler 对 "boom" panic): ``` [natspanic] benign message handled panic: handler panic (simulated) goroutine 24 [running]: main.natspanic.func1(...) /tmp/pbprobe/main.go:55 github.com/oekit/network/nats.SubscribeJSON[...].func1() /Users/zhangyi/oekit/network/nats/client.go:307 github.com/nats-io/nats.go.(*Conn).waitForMsgs(...) nats.go@v1.55.0/nats.go:3861 exit status 2 ``` ## 失败场景推演 一条业务消息 JSON 反序列化**成功**但语义残缺(可选字段为 nil、map 查不到 key)→ handler nil 解引用 panic → 穿透 `waitForMsgs` 无 recover → 进程退出。后果:该进程上**所有**订阅、所有连接、所有在途请求一并消灭;core NATS 无持久化,这条消息永久丢失、服务端零记录。SubscribeJSON 对坏 JSON 特意做了「log 后跳过」的健壮性(client.go:303-306),唯独更常见的 handler 内 panic 没兜。 ## 为什么测试没抓到 nats 包的 panic 相关测试全部是 nil ctx 兜底回归(nats_issue_fix_test.go:33 等,#79/#101 修复面),没有任何 handler panic 用例;panic 发生在上游 SDK goroutine,`-race` 也不检出。 ## 建议修复方向 Subscribe/SubscribeJSON/QueueSubscribe/QueueSubscribeJSON/Reply 的 handler 调用点包 `async.GoSafeLabeled`(panic 收编为 Error 日志 + 消息丢弃留痕,与 outbox 的「只死这条连接」同口径);至少在 godoc 显著位置明示「handler panic = 进程崩溃」。 --- 置信度:高(探针复现:进程 exit status 2 + 堆栈直指 waitForMsgs 无 recover;基线 = network 9f3d2c3) **与既有 issue 的差异**:33 条已有 issue 中 #79/#100/#101 是「API 入口 nil ctx panic」,无任何 handler panic 隔离议题;与 #54(flaky 测试)无关。
Activity
test(nats): 消除 #145 回归测试中 if-init 的 err 变量遮蔽(govet shadow)
Merge pull request #148 from oekit/fix/wave1-issue-145-146-147
zy84338719 commentedon Nov 10, 2026
已在
v0.9.2修复并发布 ✅变更内容
本条修复(在
v0.9.2的版本节里定位到):该版本 `v0.9.2` 的其余变更
关联问题单:#145。
关联问题单:#146。
关联问题单:#147。
Release: https://github.com/oekit/network/releases/tag/v0.9.2
fix(nats,wsutil): JetStream/生命周期回调 panic 收编 + 文档失实修正 + 可停 timer