Skip to content

check:error-status-conformance derives a wire status from DuplicateRecordError, a class whose code never crosses HTTP — so it requires the docs to publish a status for an in-process-only code #15749

Description

@claude

Measured while implementing #15631 (renaming the catalog's 409 conflict entry to the wire spelling UNIQUE_VIOLATION).

What the gate does

scripts/check-error-status-conformance.mjs derives the runtime side by reading, among other sources, "the error classes' own readonly status / readonly statusCode". For DUPLICATE_RECORD that derivation finds exactly ONE producer — its --report output, verbatim:

DUPLICATE_RECORD
    409  packages/objectql/src/duplicate-record-error.ts: class DuplicateRecordError

Direction A of the gate ("every status the runtime can emit for a code is documented for it") then requires some scanned page to publish 409 for DUPLICATE_RECORD.

Why that requirement is wrong

The maintainer ruling on #14723 (2026-09-03) is that a unique-constraint refusal has ONE wire spelling on every route, UNIQUE_VIOLATION; DuplicateRecordError.code stays DUPLICATE_RECORD in-process only, translated at the REST door by structuredCodeAnswer's DuplicateRecordError arm in packages/rest/src/error-response.ts, and the row derivations (toRowApiError, toFailedResult) apply the same mapping. A census of code: 'DUPLICATE_RECORD' across packages/** finds no wire producer at all — every hit is a docblock or the engine's own throw.

So the gate reads an in-process throw's declared status as "the runtime can emit HTTP 409 for this code". It cannot distinguish a code that reaches the wire from one a door translates away.

The consequence, measured

On claude/issue-15631-15632-error-docs-wire-shape, with the catalog entry renamed to the wire spelling exactly as #15631 was graded, the gate goes RED with its own verdict line:

  X DUPLICATE_RECORD: the runtime can emit HTTP 409, and no doc publishes that status for it (documented: nothing). Emitted at packages/objectql/src/duplicate-record-error.ts: class DuplicateRecordError. Document the status where it belongs — a code may carry more than one, so an exception is documented, not flattened away.
X check:error-status-conformance — 1 finding(s).

Baseline on origin/main c2a336ca2 is exit 0. So the gate is green today because content/docs/api/error-catalog.mdx publishes a 409 wire claim for a code that never crosses HTTP — the gate is currently held green by the very defect #15631 removes, and correcting the page is what turns it red.

Measured detail on the doc side

A ### \DUPLICATE_RECORD`entry heading placed under## Conflict Errors (409)is enough to satisfy direction A through the weakercovered` grade (section headings absolve but never demand) — measured: gate exit 0 with such a stub, exit 1 without it. That is an availability of a workaround, not a fix: it still catalogues an in-process constant on a client-facing wire catalog, and it silences the gate by heading placement rather than by the deriver learning the distinction.

Suggested shape

The deriver needs a notion of "a code translated at a door is not a wire producer" — the door that performs the translation is readable source (structuredCodeAnswer's arm answers code: 'UNIQUE_VIOLATION' for the DuplicateRecordError envelope), so the exclusion can be derived rather than listed. A hand-written exclusion list would be the second copy of a table this gate's own header argues against.

Not measured here

Whether other in-process-only error classes are in the same position (this was measured for DUPLICATE_RECORD only, because that is the code #15631 touches). The unpinned baseline scripts/error-status-unpinned-baseline.json is a different population — codes with NO derivable producer — and DUPLICATE_RECORD is not in it.

Refs: #14723 (the wire-spelling ruling) - #15631 (the catalog rename that surfaces this) - packages/rest/src/rest-duplicate-record-arm.test.ts.


Generated by Claude Code

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions