Skip to content

A raw driver code (SQLITE_ERROR) still reaches client-facing payloads through the batch verbs' code limb — the sibling field #8333 did not cover #8441

Description

@os-zhuang

Filed by the dev on #8333 while landing the P6–P13 producer sweep (PR #8436). Unassigned; nobody is on it. Not a defect in that PR — a different field, with a different rule, deliberately left out of its scope rather than ridden in.

The measurement

#8333 fixed the errorstring on the batch verbs' payloads: a caught sentence is quoted back only when the error declared a 4xx status. Several of those same collectors carry a sibling limb built straight off the caught object:

...(e?.code ? {code: e.code} : {})

publishPackageDrafts' failed[] and revertCommit' failed[] both have it. That limb is ungated, and drivers do carry code: better-sqlite3 raises SQLITE_ERROR, node:sqlite ERR_SQLITE_ERROR, postgres a five-character SQLSTATE.

Reproduced end to end on the #8333 branch (so, with the message fix already in place) — an insert on sys_metadata failing with Object.assign(new Error('SQLITE_ERROR: no such table: sys_metadata'), { code: 'SQLITE_ERROR', errno: 1 }), driven through publishPackageDrafts:

[
{
"type": "view",
"name": "acct_view",
"error": "publish failed",
"code": "SQLITE_ERROR"
}
]

The message is withheld exactly as #8333 intended, and the driver's own dialect still ships beside it.

Why this is a different rule, not an oversight in #8333

carryCatalogedErrorCode's docblock states the distinction, and it is load-bearing: a message is free text, so the catalog does not bound it and status-alone is the safe test; a code writes ApiErrorSchema.code, a closed union a driver's dialect must never enter. The two limbs therefore need different predicates, and #8333's positive list is the wrong tool for this one — the right test is membership in StandardErrorCode ∪ ERROR_CODE_LEDGER, which the file already has a helper for.

⇒ The likely fix is to route these limbs through the same catalog gate carryCatalogedErrorCode applies at the re-wrap exits, rather than widening declaresClientRefusal.

Scope note

Same sink as #8333failed[] rides on response data, so no HTTP boundary's message withhold reaches it. Consumers that switch on code are the reason it cannot simply be dropped: BATCH_ABORTED and the declared 4xx codes on those same arrays are read by callers, so the fix must filter, not delete.

Sites read from source (packages/metadata-protocol/src/protocol.ts, the failed.push collectors in publishPackageDrafts and revertCommit); only the publishPackageDrafts one was reproduced.

Related

#8333 (the error string, PR #8436) · #8136 (option C, the measured cluster) · #8086 (the ruling recording option C)


Generated by Claude Code

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions