Skip to content

[finding] 分片读取器 categoryOfDefKey 对「非字符串条目」抛裸 TypeError:被外层 catch 兜住,但消息不报文件名/不报条目/无 issue 锚点(三个分片产物共用) #6751

Description

@os-project-manager

范围外发现,记录于 #5873 的重锚复验过程中(该单前提已被证伪 —— 其正文指认的 authorable-surface.json 无保护 JSON.parse 已随 #5837 分片重做整体消失,详见其评论)。观察类:不构成绕过,门禁照样红、--check 照样不写盘,只是这一条错误分支的诊断质量掉回了「裸 JS 报错」。

事实

packages/spec/scripts/lib/sharded-artifacts.ts:95-104categoryOfDefKey(key: string) 直接调 key.indexOf('/')。参数类型写的是 string,但它读的是磁盘上的 JSON 数组条目 —— 一个被手编成非字符串的条目(数字、null、对象)在运行时就会让它抛裸 TypeError

它自己对「字符串但没有 category 段」这一类是会说话的:

cannot shard "foo": every ratcheted key is "category/Def[:prop]" and this one has no category segment (#5837)

缺的只是「根本不是字符串」这一格。

实测(本轮,worktree @ origin/main 252f71bd6,build-schemas.ts @ 747d2e451)

packages/spec/authorable-surface/ui.jsonkeys[0] 注入数字 12345,跑 pnpm --filter @objectstack/spec check:authorable-surface:

EXIT=1

❌ Failed to read authorable-surface/: key.indexOf is not a function

退出码对、无栈,但这条消息不报是哪个分片文件、不报是哪个条目、无 issue 锚点、无处方。读者拿到的信息量约等于零 —— 14 个分片,他得自己挨个找。

对照:同一文件同一轮,其它缺陷类都说话

同一 worktree、同一 gate,另外三种破坏方式的实测输出:

破坏方式 实测输出
删掉 ui.json 末尾 } ❌ Failed to read authorable-surface/: authorable-surface/ui.json is not valid JSON (#5837): SyntaxError: ...
keys 改成非数组 ❌ Failed to read authorable-surface/: authorable-surface/ui.json has no "keys" array (#5837).
破坏姊妹 authorable-surface.base.json ❌ authorable-surface.base.json is not valid JSON (#5235): SyntaxError: ...
keys 内注入非字符串条目 ❌ Failed to read authorable-surface/: key.indexOf is not a function

前三行都报了文件名 + issue 锚点;只有第四行退化。

影响面

categoryOfDefKey 是三个分片产物的共用路径 —— authorable-surface/schema-manifest/authorable-defaults/ 的读取都经 aggregateCategoryShards 走到它(build-schemas.ts 的三个 try/catch 分别在 :503 / :733 / :2324),所以同一条哑消息会以三种前缀出现。落点是 lib 一处,不是三处。

为什么归为观察类

建议修法(窄)

两个落点二选一,都不新增语义:

  • A(更靠近根因):categoryOfDefKeyindexOf 之前加一格 typeof key !== 'string',复用它已有的那句 message 形状。缺点是它拿不到分片文件名。
  • B(信息更全):aggregateCategoryShards 遍历 list 时顺手判类型 —— 它手里正好有 shard.name,能报出「哪个文件的哪个条目」,与相邻那句 has no "keys" array (#5837) 同族。

倾向 B:这个 reader 的既有惯例就是「报文件名 + 报条目 + 带 issue 锚点」,B 能把这一格补齐到同一水平,A 只能补到「不是裸报错」。

关联:#5873(本发现的来源单,其自身前提已被证伪)、#5837(分片重做)、#5235(姊妹 reader,对照实现)。

Metadata

Metadata

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions