fix(types): withhold the Postgres and bare-SQLite phrasings of a driver failure (#8132) - #8263
Merged
Merged
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
Contributor
📓 Docs Drift CheckThis PR changes 1 package(s): 1 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
|
This was referenced Aug 13, 2026
os-zhuang
marked this pull request as ready for review
August 13, 2026 01:41
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #8132
looksLikeInternalErrorLeakrecognised SQLite'sSQLITE_ERROR: no such table: sys_metadatabut not the Postgres phrasing of the same condition,
relation "sys_metadata" does not exist.One failure therefore disclosed a physical table name, or not, depending purely on which engine
was underneath — from every boundary that applies the predicate.
Implements option A as ruled in triage. Option C (the producer-side fix, so no driver text is
interpolated into client-facing messages) is tracked separately as #8136 and is deliberately out
of scope here.
What changed
packages/types/src/error-leak.tsgains aDIALECT_LEAK_PHRASINGSlist covering the two enginesthis repo actually runs (
driver-sql,driver-turso,driver-sqlite-wasm):relation "…" does not exist/column "…" does not existpermission denied for table|relation|sequence|database …no such table:/no such column:The bare SQLite forms are not speculative:
packages/metadata/src/utils/schema-sync-errors.tsalready documents both as shapes libsql and better-sqlite3 raise without a
SQLITE_prefix, whichis exactly what the existing
sqlite_limb needs in order to fire.No dialect this repo does not run gets an entry. The unbounded-list trap the module note warns
about is real, and
declaresServerFaultremains the answer that does not depend on phrasing.The judgment: anchoring, not keywords
A bare
includes('does not exist')would have matched "user does not exist" and started replacinglegitimate business answers with
Internal server error. Every phrasing is anchored on what thedriver always emits and prose usually does not — a quoted identifier, or the trailing colon.
The negative half is pinned as tests, including two near-misses that prove the anchor is real
rather than incidental:
This relation does not exist in the diagramandThe column layout does not existboth stayfalse. The looserincludes('relation') && includes('does not exist')reading used elsewhere would match the first of those.
permission denied foris restricted to physical object kinds.schema,view,functionandcolumnare all ObjectStack authoring vocabulary, so a product message could legitimately usethem; a miss is the cheap direction, since the outcome is already a 5xx.
The residual pin, inverted
package-door-5xx-message-sanitization.test.tscarried a deliberately-red-in-future case fromPR #8130 asserting the predicate returned
falsefor the Postgres line. It is inverted into thepositive assertion rather than deleted, and now asserts the full withheld envelope — so the pair
of cases proves that door answers the same envelope for both dialects of one failure. The
option-C pointer survives in the comment, since a phrasing test can only know the dialects
someone has met.
That is the only
packages/resttouch, keeping clear of #8039's landing inrest-server.ts.Verification
packages/types— 246/246 pass. New cases measured red first against the unfixed predicate(10 positives failing, negatives already green), then green after the change.
packages/runtime— 2301/2301 pass, no flips.packages/rest— 1756/1756 pass. Before the pin flip: exactly one failure, the namedresidual pin and nothing else.
typecheckgreen on all three packages.check:authz-resolver,check:cross-package-test-inputs,check:filter-alias-parity,check:meta-type-normalized,check:query-options-erasure,check:type-check-coverage,check:nul-bytes, plus five changeset-triggered families surfaced by re-deriving against theactual diff — all green.
Verified at every call site that the predicate still only ever runs where the outcome is already a
5xx. Seven call sites: four guard on
httpStatus >= 500, two build a hard-coded 500, andrest-server.ts's classifier chooses betweenDATA_STORE_FAULTandUNCLASSIFIED_FAULT, both ofwhich are status 500. One nuance worth recording: at that classifier the predicate selects which
sanitised 500 envelope is returned, so a false positive there shifts
INTERNAL_ERRORtoDATABASE_ERROR— a code change, never a disclosure.Generated by Claude Code
Generated by Claude Code