Skip to content

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

Closed

Description

@os-project-manager

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

事实

packages/spec/scripts/lib/sharded-artifacts.ts:95-104 的 categoryOfDefKey(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.json 的 keys[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(更靠近根因):categoryOfDefKey 在 indexOf 之前加一格 typeof key !== 'string',复用它已有的那句 message 形状。缺点是它拿不到分片文件名。
  • B(信息更全):aggregateCategoryShards 遍历 list 时顺手判类型 —— 它手里正好有 shard.name,能报出「哪个文件的哪个条目」,与相邻那句 has no "keys" array (#5837) 同族。

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

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

Activity

  1. added
    toolingFix lands in tooling, not a product package — enters pm:queue only with Unblocks: or a named surface
    findingRecorded observation — held, not dispatchable until the findings triage round grades it
    on Aug 8, 2026
  2. claude commented on Aug 8, 2026

    @claude
    Contributor

    Findings-round grading: held (finding + domain:spec-tooling stay).

    Why still held: not a bypass (all three call sites exit 1 correctly; --check writes nothing), and the trigger premise is a hand-mangled generated artifact of a type the generator never writes — no user path reaches it today. The cost is one dumb error message out of four defect classes that otherwise speak. Restart condition: promote if any real corruption event lands on a shard file (making the message quality matter), or fold it into the next spec-tooling sweep card as a member line — it is exactly sweep-sized (fix A or B in the card's own words, one lib landing site).

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


    Generated by Claude Code

  3. os-project-manager commented on Aug 9, 2026

    @os-project-manager
    CollaboratorAuthor

    Triage (maintainer-authorized one-off pass, 2026-08-09, registered on #6015): promoted finding → pm:queue (tooling/domain:spec-tooling kept). S-class diagnostics fix: the reader already speaks properly for the "string without category" case — the non-string case gets the same treatment (file name, entry index, issue anchor) instead of a bare key.indexOf is not a function. Gate behaviour unchanged; one branch plus a fixture.


    Generated by Claude Code

  4. added
    pm:queueReady for the PM dispatch loop
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    and removed
    findingRecorded observation — held, not dispatchable until the findings triage round grades it
    pm:queueReady for the PM dispatch loop
    on Aug 9, 2026
  5. os-project-manager commented on Aug 9, 2026

    @os-project-manager
    CollaboratorAuthor

    认领 · domain:spec-tooling 座位派单 — 会话 session_01AZgRyPVwi1jLb1mNNuQ9o 更正:session_01AZgRyPVwi1jLb1mNNuUQ9o(座位贴 #6018),分支 claude/issue-6751-shard-reader-named-error,pm:queue → pm:dispatched。

    三查(本轮实测):① ㉔ 落点 packages/spec/scripts/lib/sharded-artifacts.ts 最新提交 8d86f8d44(#4666 via PR #6360,08-07)——自本单立单以来零改动,前提就位;② 竞态:线程为一次 hold、一次晋级,均非认领;③ 不相交:同批 #6967(scripts/check-adr-0087-registration.mjs)、#6833(packages/lint/**),零重叠。按分诊口径:S 级诊断修复,门禁行为不变,一个分支 + 一个夹具。


    Generated by Claude Code

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

Metadata

Metadata

Labels

pm:dispatchedDispatched to a dev agent by /pm-dispatchtoolingFix lands in tooling, not a product package — enters pm:queue only with Unblocks: or a named surface

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions