Skip to content

plugin-hono-server 适配器把逃出 handler 的抛出整个丢弃:裸 500 + 零日志(#4264 只按路由治了标) #5848

Description

@hotlong

在 cloud#1097(生产控制面 5xx 定位)里核到的,与那单无关,是独立问题。未 assign,交 PM 分诊。

事实

packages/plugins/plugin-hono-server/src/adapter.ts,framework main f886f291

  • runHandler() 跑路由 handler,handler 一旦 reject:

    }).catch((_err) => {
        _endHandler?.();
        closeStream();
        resolve({ response: null, failed: true });
    });
    

    参数名就叫 _err——被显式丢弃,没有任何日志。

  • wrap() 于是回兜底响应:

    return response ?? c.json({ error: 'No response from handler' }, 500);
    

净效果:任何逃出 handler 的抛出,在这个平台上表现为

  1. 一个 非信封 的 500(error 是裸字符串、无 success、无 error.message、无 code),且
  2. 任何地方都没有日志——原因彻底消失,连 stack 都没有。

为什么这不是 #4264 的重复

#4264(已关闭)诊断的正是这段代码,原文写得很准:「handler 的 rejection 被吞掉…真实原因彻底丢失(甚至没有日志)」。但它的修法是按路由加 catch(三条 datasource 路由),接缝本身没动——上面这段在 main 上一字未改。所以:

建议方向(待裁决,不预设)

至少要有日志:在 .catch 里把错误按 serializeError 那类不丢 message/stack 的形状打出来(Errormessage/stack 是 non-enumerable,直接塞进结构化 meta 会变成 {}——cloud objectos-runtime/src/safe-log.ts 的头注释把这个坑写全了)。

是否顺带把兜底 body 收成声明信封是另一个决策(会改线上响应形状),建议单独裁决,不要和「补日志」捆绑——补日志是纯增益、零风险的那一半。

影响到谁

任何以这个适配器为 transport 的 host。具体动机:ObjectStack Cloud 的控制面在生产上出现过裸 5xx 而日志里什么都没有;cloud 侧只能在自己的路由里逐条 try/catch + rethrow 去补(cloud#1144 对 POST /cloud/licenses/issue 就是这么做的),而那显然是在替这个接缝还债。

证据强度

:main 上的代码直读,无需复现环境。


Generated by Claude Code

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions