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

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions