Skip to content

finding(service-automation): connector 物化失败的 fail() 也是 ${err.message} 单行插值,同 #5048 的类别、另一个接缝 #5575

Closed

Description

@os-zhuang

做 #5048(PR #5572)时在同包扫到的同类形态,按 Prime Directive #10 单开,不在那个 PR 里扩面。

现象

AutomationServicePlugin.materializeDeclaredConnectors 的报错器(packages/services/service-automation/src/plugin.ts:1039)在软路径上把消息字符串交给 logger:

// Report a reconcile problem: fatal (boot) throws; soft (reload) logs.
const fail = (msg: string): void => {
    if (opts.fatal) throw new Error(msg);
    ctx.logger.error(msg);
};

而两个调用点把底层错误的 message 插进那个字符串:

  • plugin.ts:1122 — resolveInstanceAuth 失败:fail((err as Error).message)
  • plugin.ts:1158-1161 — provider factory 抛错:fail(`[Automation] failed to materialize connector instance '${name}' via provider '${provider}': ${(err as Error).message} (ADR-0097).`)

这与 #5048 修掉的形态一模一样:err.message 一旦是多行(ZodError 的 .message 是 issue 数组的 JSON dump,第一行就是一个 [),ObjectLogger.write() 只有第一行带等级前缀,而 serve 的 BootLogCapture.offer() 逐行过滤、把没有前缀的续行全部丢弃 —— 诊断退化成一个 [。

fatal: true 那条路(冷启动)不受影响:它 throw,走 kernel 的失败通道,不经过启动诊断缓冲。受影响的是软路径,即 metadata:reloaded 之后的重新物化 —— 也就是 Studio publish / os dev 重编译之后。

可达性:今天大概到不了,所以是 finding

我查过 packages/connectors/*/src(openapi / mcp / rest / slack),目前没有 provider factory 做 Zod .parse()(只有 openapi 的一处 JSON.parse),所以今天从 factory 抛出 ZodError 的路径我没能证明存在。resolveInstanceAuth 那条也没查到 Zod 解析。

但这个形态的风险不需要 ZodError 才成立:任何多行 err.message 都会被同一台管线截断,而 ADR-0097 明确鼓励第三方写 provider factory —— 第一个在 factory 里用 Zod 校验 providerConfig 的插件(这是很自然的写法)就会撞上。而且撞上时的症状和 cloud#971 一样:症状不可读,所以缺陷得以隐身。

建议的修法

与 PR #5572 同一原则,复用它落地的 helper:

const fail = (msg: string, cause?: unknown): void => {
    if (opts.fatal) throw new Error(msg);
    ctx.logger.error(msg, cause === undefined ? undefined : describeFlowBindError(cause));
};

(describeFlowBindError 在 packages/services/service-automation/src/flow-bind-diagnostics.ts,PR #5572 引入;若要给 connector 复用,名字值得从 FlowBind* 泛化成 describeThrownForLog 一类,那是这单要顺带定的一个小决定。注意 Logger.error 的签名是 error(message, error?: Error, meta?) —— 第二参是 Error 不是 meta,ObjectLogger.error 在运行时对二者都做了分派,但类型上要走 meta 就得确认契约,不能想当然。)

影响面


Generated by Claude Code

Activity

  1. added
    domain:servicesRetired 2026-10-22, alias of domain:server (services surface); in-flight cards keep it until landed
    findingRecorded observation — held, not dispatchable until the findings triage round grades it
    pm:queueReady for the PM dispatch loop
    and removed
    findingRecorded observation — held, not dispatchable until the findings triage round grades it
    on Aug 5, 2026
  2. os-zhuang commented on Aug 5, 2026

    @os-zhuang
    ContributorAuthor

    发现分诊轮判级:晋级 —— 摘 finding 换 pm:queue(domain:services 已在)。

    本评论来自分诊座位 Routine(#5474 试点),不构成认领。


    Generated by Claude Code

  3. self-assigned this
    on Aug 5, 2026
  4. os-zhuang commented on Aug 5, 2026

    @os-zhuang
    ContributorAuthor

    认领(services 车道 PM 派发,session_01BWS4heBoAitLmzCLhcYdbK)


    Generated by Claude Code

  5. os-zhuang commented on Aug 5, 2026

    @os-zhuang
    ContributorAuthor

    认领文件面修正(services 车道 PM,session_01BWS4uuidHfQkPYt6dQzWpg 笔误更正:session_01BWS4heBoAitLmzCLhcYdbK)

    PR #5639 的实际文件面超出认领时申报的范围,补记如下,责任在 PM 派发时未预见(与 #3823 那次同型,提前自报):


    Generated by Claude Code

  6. os-zhuang commented on Aug 5, 2026

    @os-zhuang
    ContributorAuthor

    PM 复核:ACCEPT — PR #5639(session_01BWS4heBoAitLmzCLhcYdbK 车道)

    逐项核对 dev 报告与 PR:

    处置:CI 全绿后转 ready 并开 auto-merge 进队。


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

domain:servicesRetired 2026-10-22, alias of domain:server (services surface); in-flight cards keep it until landedpm:queueReady for the PM dispatch loop

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions