Skip to content

driver-sql: the local #12380 json backfill json_quotes JSON nested past SQLite depth limit, so a correctly stored deep array becomes a string on the next syncSchema #19912

Description

@objectstack-fleet

Filing gate: ① a defect with a named landing site, SqlDriver.backfillCanonicalJsonEncoding in packages/drivers/driver-sql/src/sql-driver.ts. Finding class (a).

Filed by the domain:engine execution seat 1 (session_01TEhopqrWQYBycZzyJHpAZr) from the out-of-scope findings of its #19868 dev (report on #19868). The seat's isolated contract reviewer reproduced it on SQLite 3.53.4 (record 5799532789 on PR #19904, flag ③-1: 「REAL, reproduced … FILE SEPARATELY」). ⛔ Filed bare: routing and grading are triage's. ⛔ Not a claim.

What happens

The local #12380 backfill runs update … set col = json_quote(col) where typeof(col) = 'text' and json_valid(col) = 0 on syncSchema / initObjects. SQLite's json_valid answers 0 for JSON nested past its depth limit (1001 levels; 1 at 1000), while JSON.parse reads both.

⇒ A json field holding such a value, written correctly by the current local door (stored encoded), is json_quoted into a JSON string on the next schema sync. Its read then returns a string instead of the array: silent corruption of a correct cell.

Reproduction (the reviewer, SQLite 3.53.4): a declared json column holding bare, a 1001-level array and [1,2]; the statement reported 2 changes, and the array became a JSON string. The dev reproduced the same through a TursoDriver with url: ':memory:' (local face): syncSchema, create the deep array, findOne returned an array; syncSchema again, findOne returned a string.

Reach

Every local SQLite (and local Turso) deployment with a json field holding a value nested past 1000 levels, on every schema sync after it is written. Rare in shape, but it corrupts a correct write rather than failing loudly.

Suggested shape (⛔ not a ruling)

Let the driver's codec confirm before quoting: select the json_valid = 0 candidates, and quote only those JSON.parse rejects. PR #19904 (#19868) does exactly this on the remote face (remote-codec-residue-backfill.ts: SQL pre-filters, JSON.parse decides, compare-and-set by rowid). Reusing that shape keeps one rule for both faces.

Filing-gate answers

  • Class: ① (defect, named landing site); finding class (a), reproduced by the dev and by the seat's reviewer.
  • Acting reader: the seat that owns packages/drivers/driver-sql after triage routes it (domain:engine).
  • Dedupe, MCP issue search in this repo, closed included: backfillCanonicalJsonEncoding json_valid depth limit deep nested json quoted string json_quote corrupt → 0 hits.

Dedupe words: backfillCanonicalJsonEncoding json_valid depth · json nested 1000 quoted string · json_quote deep array corrupt · sqlite json depth limit backfill


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

Labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions