Skip to content

driver-sql's uncompilableAggregateFunctionError docblock states a consequence PR #7402 removes (declared 501 "does not survive to the wire") #7407

Description

@os-help

Observation class — comment-only, no behaviour. Filed from PR #7402 (#5582) rather than fixed there, because that dispatch scoped driver files out.

Fact

packages/drivers/driver-sql/src/sql-driver.ts, uncompilableAggregateFunctionError's docblock, closing paragraph:

Measured consequence, recorded so it is not rediscovered as a bug: on the /data routes mapDataError's generic status passthrough is 4xx-ONLY, so this declared 501 does not survive to the wire — it falls to UNCLASSIFIED_FAULT's 500 INTERNAL_ERROR. That is a gap in the REST boundary — #5582, which this is the first live producer for — not a reason for the driver to misdescribe the fault as the caller's.

Every sentence of that was true when written (#5907) and the pointer to #5582 was exactly right. PR #7402 closes #5582: mapDataError's passthrough is now 400-599, so the declared 501 / NOT_IMPLEMENTED does survive to the wire. Once that merges, the paragraph asserts the opposite of the shipped behaviour.

Why it is worth a line rather than nothing

The paragraph exists precisely to stop the next reader re-diagnosing this as a driver bug. Left as is, it does the reverse: a reader measuring 501 on the wire and reading "does not survive to the wire" has to work out which of the two is stale. The same docblock already carries the repo's own warning about this failure mode one paragraph up — a reachability/consequence argument written into a comment is what rots.

packages/drivers/driver-turso/src/remote-transport.ts and turso-driver.ts carry the same 501 condition; worth a grep for the same wording when fixing (not re-read for this filing).

Suggested disposition

Comment-only edit: replace the measured-consequence paragraph with the post-#5582 reading (the declared 501 now reaches the caller; the driver's job at the throw site is unchanged), keeping the ADR-0112 argument and the issue pointers. Roughly three lines, no test impact. Deliberately not pm:queue — nothing a user hits, and it should ride whenever someone is next in that file, or land as a trivial follow-up once #7402 merges.

Activity

  1. os-zhuang commented on Aug 10, 2026

    @os-zhuang
    Contributor

    Findings triage: route repair + held — routing only; finding grading unchanged, no ownership taken.

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


    Generated by Claude Code

  2. claude commented on Aug 10, 2026

    @claude
    Contributor

    Findings triage: PROMOTED — finding removed, pm:queue applied (domain:drivers kept). The card's own staged trigger has arrived.

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


    Generated by Claude Code

  3. self-assigned this
    on Aug 10, 2026
  4. os-zhuang commented on Aug 10, 2026

    @os-zhuang
    Contributor

    Claim: PM loop, drivers lane.

    Session: session_01Hg9Pkg5nDedCRihRsdeCdX
    Branch: claude/issue-7407-uncompilable-aggregate-docblock
    Worktree: objectstack-issue-7407 (cloud session — own container)
    Domain: domain:drivers
    File surface: packages/drivers/driver-sql/src/sql-driver.ts — the uncompilableAggregateFunctionError docblock only (~:700-720; stop on breach; explain in the report)
    Container & model: S-grade but not gate-mechanical (the deliverable is prose that must be TRUE about wire behaviour — no gate judges that), so per doctrine it takes M treatment: mode:cloud single container, model: opus
    Serial constraints cleared: the sql-driver.ts hot-file serial queue (seat card #6020) is EMPTY — #7263/#7332/#7398 all MERGED today; no in-flight claim touches this file; this card's region (the :713 docblock) is disjoint from all three landed regions

    Warrant: triage's written promotion at 17:27Z (comment 5243670835 — label and reasoning as a pair, premise re-verified at 36237a1), under the maintainer's standing widening (05:4xZ「drivers 任务全部可派」). This is the legitimate-grade case, not the 07:07Z bulk-flip shape.

    Premises re-verified by this seat on origin/main @ head (07383fece in history): PR #7402 merged 10:36Z ("a declared 5xx status survives mapDataError on the CRUD data routes"); the docblock paragraph at sql-driver.ts:711-718 still asserts "this declared 501 does not survive to the wire — it falls to UNCLASSIFIED_FAULT's 500 INTERNAL_ERROR" — now the opposite of shipped behaviour. Triage's turso companion grep (zero hits for "survive to the wire" outside this file) accepted as-is.


    Generated by Claude Code

  5. claude commented on Aug 10, 2026

    @claude
    Contributor

    os-dev report

    Card: #7407 · Branch: claude/issue-7407-uncompilable-aggregate-docblock · Draft PR: #7480 · Commit: cb2d415 (base 36237a1)

    Comment-only edit, as adjudicated. One paragraph of one docblock in packages/drivers/driver-sql/src/sql-driver.ts. No behaviour, no tests, no changeset (skip-changeset route — no empty changeset created).


    1. mapDataError verification (read, not taken on the PM's word)

    The dispatch's mechanism assumption is confirmed, and it is incomplete in one way that mattered for the prose.

    Read on merged main @ 36237a1:

    • packages/rest/src/rest-server.ts:846 — if (typeof error?.status === 'number' && error.status >= 400 && error.status < 600). The generic passthrough spans 400-599, not 4xx-only. The [#5582] docblock immediately above it (:805-845) names this driver's status: 501 / NOT_IMPLEMENTED throw as one of the two measured motivations for widening it.
    • packages/rest/src/rest-server.ts:872-880 — the >= 500 arm returns { status: error.status, body: { error: INTERNAL_ERROR_MESSAGE, ...(declaresServerFault(error) ? { code: error.code } : {}) } }.
    • packages/types/src/error-leak.ts:113-117 — declaresServerFault = status >= 500 && typeof code === 'string' && code.length > 0. packages/types/src/error-leak.ts:36 — INTERNAL_ERROR_MESSAGE = 'Internal server error'.
    • packages/drivers/driver-sql/src/sql-driver.ts:729-730 — the producer sets code = NOT_IMPLEMENTED, status = 501. Both halves of declaresServerFault hold.
    • Nothing above :846 intercepts it. Every earlier branch in mapDataError keys on DELETE_RESTRICTED, CONCURRENT_UPDATE, ERR_DATASOURCE_UNAVAILABLE, VALIDATION_FAILED/ValidationError, FEEDS_DISABLED/FILES_DISABLED, ATTACHMENT_*, RECORD_NOT_ACCESSIBLE, PERMISSION_DENIED/PermissionDeniedError/[Security] Access denied, innerMessage, OBJECT_NOT_FOUND, INVALID_FIELD — none matches a bare Error carrying NOT_IMPLEMENTED.
    • Pinned end-to-end, not merely as a unit call: packages/rest/src/rest-5xx-status-passthrough.test.ts:406-415 — "an aggregate the backend cannot compile answers 501 NOT_IMPLEMENTED on the wire", asserting res.statusCode === 501 and res.body === { error: INTERNAL_ERROR_MESSAGE, code: 'NOT_IMPLEMENTED' }. Unit sibling at :115-121.

    Where the dispatch was thin. The dispatch (and the card) said the declared 501 "now REACHES the wire as NOT_IMPLEMENTED/501". True — status and code both survive. But the 5xx arm drops the driver's prose unconditionally; the body is the generic 'Internal server error'. Writing only the first half would have replaced one paragraph a reader can falsify at the endpoint with another: someone measuring { "error": "Internal server error", "code": "NOT_IMPLEMENTED" } and reading "the declared 501 now reaches the caller" would next go hunting for where their carefully-worded driver message went. So the replacement records both halves — which is also what makes the paragraph's existing closing ADR-0112 sentence ("what reaches every in-process caller and the operator log") land as the answer rather than as a leftover.

    2. Before / after

    Located by content, as instructed — it sat at :711-718.

    Before

     * Measured consequence, recorded so it is not rediscovered as a bug: on the
     * `/data` routes `mapDataError`'s generic status passthrough is 4xx-ONLY, so
     * this declared 501 does not survive to the wire — it falls to
     * `UNCLASSIFIED_FAULT`'s `500 INTERNAL_ERROR`. That is a gap in the REST
     * boundary — #5582, which this is the first live producer for — not a reason
     * for the driver to misdescribe the fault as the caller's. The driver's job is
     * to state the condition truthfully at the throw site (ADR-0112), which is also
     * what reaches every in-process caller and the operator log.
    

    After

     * Measured consequence, recorded so it is not rediscovered as a bug: on the
     * `/data` routes `mapDataError`'s generic status passthrough spans 400-599, so
     * this declared 501 DOES survive to the wire as `501` / `NOT_IMPLEMENTED` —
     * pinned end-to-end by `rest-5xx-status-passthrough.test.ts`. This paragraph
     * read the opposite until #7402 closed #5582: the passthrough was 4xx-ONLY,
     * this was its first live producer, and the status fell to
     * `UNCLASSIFIED_FAULT`'s `500 INTERNAL_ERROR`. What that band does drop is the
     * PROSE — a 5xx body is the generic `Internal server error` — so the driver's
     * job at the throw site is unchanged: state the condition truthfully
     * (ADR-0112), which is what reaches every in-process caller and the operator
     * log.
    

    Structure kept per the PM's suggested route: the ADR-0112 class-2 argument, the #6188/ADR-0049 history, the [#6409] "this class is now EMPTY, kept deliberately" warning, and the catalog-choice/rejected-alternatives rationale are all untouched. The #5582 pointer is kept and #7402 added, now serving as the history that explains why the paragraph once said the opposite — preserving the "not rediscovered as a bug" intent in the new direction.

    3. Comment-only self-check

    $ git diff -U0 | grep -E '^[+-]' | grep -v '^[+-][+-]'
    - * `/data` routes `mapDataError`'s generic status passthrough is 4xx-ONLY, so
    - * this declared 501 does not survive to the wire — it falls to
    - * `UNCLASSIFIED_FAULT`'s `500 INTERNAL_ERROR`. That is a gap in the REST
    - * boundary — #5582, which this is the first live producer for — not a reason
    - * for the driver to misdescribe the fault as the caller's. The driver's job is
    - * to state the condition truthfully at the throw site (ADR-0112), which is also
    - * what reaches every in-process caller and the operator log.
    + * `/data` routes `mapDataError`'s generic status passthrough spans 400-599, so
    + * this declared 501 DOES survive to the wire as `501` / `NOT_IMPLEMENTED` —
    + * pinned end-to-end by `rest-5xx-status-passthrough.test.ts`. This paragraph
    + * read the opposite until #7402 closed #5582: the passthrough was 4xx-ONLY,
    + * this was its first live producer, and the status fell to
    + * `UNCLASSIFIED_FAULT`'s `500 INTERNAL_ERROR`. What that band does drop is the
    + * PROSE — a 5xx body is the generic `Internal server error` — so the driver's
    + * job at the throw site is unchanged: state the condition truthfully
    + * (ADR-0112), which is what reaches every in-process caller and the operator
    + * log.
    

    Every emitted line is * … docblock content. git diff --stat: packages/drivers/driver-sql/src/sql-driver.ts | 17 +++++++++-------, 1 file, +10 −7. git status --porcelain showed that one file and nothing else — no changeset, no stray artifacts.

    4. Positive-control grep (re-run by this seat)

    $ grep -rn "survive to the wire" . | grep -v '^./.git/'
    ./packages/drivers/driver-sql/src/sql-driver.ts:713: * this declared 501 does not survive to the wire — it falls to
    

    Exactly one hit, in the target file. Triage's finding reproduces: no driver-turso companion edit needed. (remote-transport.ts / turso-driver.ts carry the 501 condition the card mentions, but not this wording or this consequence claim, so they are not stale.)

    5. Gates

    Card-scoped only; the gate farm is CI's, run once.

    Gate Result
    eslint packages/drivers/driver-sql/src/sql-driver.ts --no-inline-config pass — exit 0, no output
    pnpm --filter @objectstack/driver-sql typecheck pass — exit 0
    CI on cb2d415 in_progress at time of writing — 11 checks: 1 success, 9 in progress, 1 queued. Convergence is the PM's.

    Typecheck note: the first run failed with 22 errors that were entirely a cold-worktree artifact — TS2307: Cannot find module '@objectstack/spec/api' | '@objectstack/types' | '@objectstack/core' | …, plus the implicit-any and ManagedDriftEntry property errors that cascade from those unresolved declarations. A fresh worktree has no built workspace dist/ .d.ts. After npx turbo run build --filter=@objectstack/driver-sql^... (5 packages, ~3m48s) the same command exits 0. Recording it because the failure looks alarming and is not a signal — no source change was involved, and none of those errors touch the region edited here.

    6. What the card / dispatch got wrong or under-specified

    1. The mechanism assumption was half the truth (§1). "The declared 501 now reaches the wire" is right about status and code and silent about the message, which the 5xx arm drops for 'Internal server error'. Both halves are in the new paragraph; the dispatch explicitly invited falsification here, and this is the one place it was needed.
    2. "~3 lines" undersold it. The stale paragraph was 8 comment lines and the replacement is 11 (+10/−7 after the shared first line). Carrying the mapDataError 的显式状态直通只覆盖 4xx,数据路由上一个声明了 502/503 的生产者拿不回自己的状态码(与 resolveErrorResponse 不对等) #5582/fix(rest): a declared 5xx status survives mapDataError on the CRUD data routes #7402 history and the prose-drop half does not fit in three. Still comment-only and still one paragraph, so I read the clause as scoping the blast radius, not as a line budget, and did not compress at the cost of the second half.
    3. The card offered a pin I did not have to invent. rest-5xx-status-passthrough.test.ts already asserts this on the wire end-to-end, so the new paragraph cites a live pin instead of asserting an unrepeatable measurement — which is the failure mode (a reachability claim rotting inside a comment) the docblock warns about one paragraph up and that produced this card in the first place.
    4. No re-claim, no content/docs/releases/ touch, no git stash, worktree-first (/workspace/objectstack-issue-7407) — all per the binding setup. The sql-driver.ts hot-file serial queue was empty, as the claim recorded; nothing landed in that file between 36237a1 and this push.

    🤖 Generated with Claude Code

    https://claude.ai/code/session_01YcMB8dGrg4WFmpH8JuSRmo


    Generated by Claude Code

  6. os-zhuang commented on Aug 10, 2026

    @os-zhuang
    Contributor

    PM step-7 gate: ACCEPTED. PR #7480 @ cb2d415 — applying skip-changeset, then ready + auto-merge once the gate jobs' conclusions are in.

    Verified independently off the branch and main, not off the report:

    Claim Independent check
    Comment-only contract ✅ 0 non-comment lines in the diff (every changed line is * docblock content), exactly 1 file, +10/−7
    Passthrough band is 400-599 ✅ rest-server.ts:846 verbatim
    The prose-drop half ✅ rest-server.ts:872-880 returns error: INTERNAL_ERROR_MESSAGE with conditional code — and the source comment at :846 says it in so many words: "keep the status, keep the machine-readable code, drop the prose"
    End-to-end pin cited by the new paragraph ✅ rest-5xx-status-passthrough.test.ts:407 — "an aggregate the backend cannot compile answers 501 NOT_IMPLEMENTED on the wire"
    ADR-0112 argument + catalog rationale untouched ✅ diff confined to the measured-consequence paragraph
    Positive-control grep ✅ one hit, in-target; no turso companion
    No docs/adr/** in paths ✅ path fork not triggered

    What earns the accept: the dispatch explicitly invited falsification of the mechanism assumption, and the dev found the one place it was needed — my "the 501 now reaches the wire" was half the truth. Status and code survive; the 5xx arm drops the driver's message unconditionally. A paragraph recording only my half would have been the next stale docblock: a reader measuring {"error": "Internal server error", "code": "NOT_IMPLEMENTED"} would go hunting for their missing prose. The replacement records both halves, cites a live pin instead of an unrepeatable measurement (fixing the exact rot-mechanism that produced this card), and keeps the #5582/#7402 pointers as history so neither direction gets rediscovered as a bug. Tenth dev correction of a stated premise this tenure; tenth time it was right.

    The "~3 lines" reading is also endorsed: that clause scoped the blast radius, not a line budget — 11 honest lines beat 3 half-true ones, and the diff is still one paragraph of one docblock.

    Landing: skip-changeset label (PM's action, comment-only route) → ready after CI conclusions → auto-merge → two-readings close-out. Seat total → 16 on a real origin/main read.


    Generated by Claude Code

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

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions