Skip to content

Measured set: five read seams answer a failed read from an empty accumulator with no log and no field saying the answer is incomplete #8896

Description

@os-project-manager

Filed from #8845's measurement (the gate card measured this class and deliberately did not extend the rule; these seams therefore need their own disposition). Unassigned. Not a claim.

Measured on origin/main @ 8664a2c, across the read-seam rule's three scan roots.

The shape

A catch that returns nothing — it falls through, or jumps — above a value that was supposed to be filled by the read. The caller receives an answer indistinguishable from a legitimate one, and no surface says otherwise. Per ADR-0110 D3 those are different facts.

check:durability-log-level cannot see any of these: its read-seam rule classifies a catch by the expression it returns, and these return none. All five are counted in its census and reported as no invented answer.

The set

Excluding diffMetaItem (that seam's disposition is #8833, with the maintainer) and cascadeDeleteRelations (filed separately as #8895 — it is an integrity bypass, not a reporting gap).

seamwhat the caller gets
metadata-protocol/src/seed-loader.ts:2058loadExistingRecords()catch { /* Object may not have records yet */ } returns an empty Map. The upsert-key match then finds nothing, so "cannot read the object" is treated as "no existing rows" — the replay-skip decision this map exists to make is inverted, and the loader writes rows it should have skipped.
metadata-protocol/src/protocol.ts:8961searchAll()Per-object catch { continue; }. Objects whose read failed contribute no hits, but the response still reports totalHits: hits.length and truncated as though the scan were complete.
metadata-protocol/src/protocol.ts:16982findReferencesToMeta()Per-matcher catch { return; } inside a Promise.all. The returned out[] is silently missing every reference from the source types whose read failed — and this answer drives "what would break if I delete this".
metadata-protocol/src/protocol.ts:4733getMetaDiagnostics()catch { continue; } drops the whole type from the diagnostics report. The comment reads "Type not listable in this kernel scope", which is one real reason among several; a store outage produces the same silent omission.
objectql/src/lifecycle/lifecycle-service.ts:805checkGovernance()catch { continue; } on the row count. The object is skipped for quota and growth alerting, and is also dropped from nextCounts, so the growth baseline for the next sweep is lost too.

Lowest-severity first read: the last two are reduced functionality; the first three hand a caller an answer it will act on.

A sixth, different in kind

metadata-protocol/src/protocol.ts:13830publishPackageDrafts() does not fall through — it pushes a fabricated entry:

}catch{commitItems.push({type: d.type,name: d.name,existedBefore: false,prevVersion: null});}

Two things to check there. existedBefore: false means "revert = soft-remove"; if the item did exist, a later revert deletes it instead of restoring the previous version. And the comment five lines above says a capture failure "just omits that item from the revert plan", which is not what the code does. Either the comment or the code is wrong; worth a look from whoever owns the revert plan.

Suggested disposition

These share one question — what should a read seam do when the read fails and the answer is an accumulator? — and the repo already has both answers in its vocabulary: discriminate with isMissingTableError and treat only that as truthful emptiness, or carry an explicit "incomplete" fact in the response. Several of the correct seams nearby already do the second (build-probes' issues[], the dangling-reference audit's report.unreadableObjects, history-cleanup's errors counter).

Related

Metadata

Metadata

Assignees

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions