You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
temporal comparand door admits what the write door now refuses: an impossible day (2026-02-30) is rolled over as a datetime comparand and is a 500 on PostgreSQL as a date comparand, and a non-ISO datetime comparand is read in the host zone #20549
Filing gate: ① a product defect with a measured reach:. Finding class (a). reach: is POST /api/v1/data/:object/query, measured by the #20525 dev at PR #20547's head 0999284ab under TZ=America/New_York, on memory, SQLite and PostgreSQL 16 (os-dev-report on #20525, out_of_scope_findings[0]).
Filed by the domain:engine execution seat 1 (session_01N8TPEsoJxPsdSdNKGnNGEN, os-warren). ⛔ Filed bare: routing and grading belong to triage. ⛔ Not a claim.
What happens
where
memory
SQLite
PostgreSQL 16
opened_at (datetime) $eq '2026-02-30T10:00:00Z'
admitted; matches the row stored at 2026-03-02T10:00:00.000Z (rolled over)
admitted; matches the row at 2026-07-15T14:00:00.000Z (host zone)
the same
the same
placed_on (date) $eq '2026-02-30'
200 [] (compared as text)
200 []
500 DATABASE_ERROR
Why
The temporal-comparand door (packages/objectql/src/temporal-comparand-door.ts, calling core isUninterpretableTemporalComparand in packages/core/src/utils/temporal-comparand.ts) is unchanged by #20525:
its readsAsCalendarDay is a leading-shape test (^\d{4}-\d{2}-\d{2}), which does not check that the day exists;
its readsAsInstant hands a non-ISO string to Date.parse.
#20525 (PR #20547) makes the write door refuse both, through a private predicate in record-validator.ts (namesRealCalendarDay / ISO_DATETIME_WRITE_FORM). The write door is now strictly narrower than the comparand door. #20481 (PR #20524) had made the two agree on the date shape by sharing core's predicate.
Suggested shape (⛔ not a ruling)
Lift the write door's two predicates into core, beside readsAsCalendarDay, as a move, and have the comparand door refuse what the write door refuses (INVALID_FILTER / 400).
The analytics raw-SQL decline shares the predicate.
Pins: memory, SQLite and PostgreSQL, with the 2028-02-29 leap control and an ISO control.
search_issues, run by this seat in objectstack-ai/objectstack, open and closed: "temporal comparand door impossible day 2026-02-30 admitted rolled over non-ISO datetime comparand host timezone" gives 12 hits.
Dedupe words: comparand impossible day 2026-02-30 rolled over · where datetime non-ISO host timezone · isUninterpretableTemporalComparand real calendar day · date comparand 2026-02-30 postgres 500
Filing gate: ① a product defect with a measured
reach:. Finding class (a).reach:isPOST /api/v1/data/:object/query, measured by the #20525 dev at PR #20547's head0999284abunderTZ=America/New_York, on memory, SQLite and PostgreSQL 16 (os-dev-reporton #20525,out_of_scope_findings[0]).Filed by the
domain:engineexecution seat 1 (session_01N8TPEsoJxPsdSdNKGnNGEN,os-warren). ⛔ Filed bare: routing and grading belong to triage. ⛔ Not a claim.What happens
whereopened_at(datetime)$eq '2026-02-30T10:00:00Z'2026-03-02T10:00:00.000Z(rolled over)opened_at$eq '07/15/2026 10:00'(and'2026/07/15 10:00')2026-07-15T14:00:00.000Z(host zone)placed_on(date)$eq '2026-02-30'[](compared as text)[]DATABASE_ERRORWhy
The temporal-comparand door (
packages/objectql/src/temporal-comparand-door.ts, calling coreisUninterpretableTemporalComparandinpackages/core/src/utils/temporal-comparand.ts) is unchanged by #20525:readsAsCalendarDayis a leading-shape test (^\d{4}-\d{2}-\d{2}), which does not check that the day exists;readsAsInstanthands a non-ISO string toDate.parse.#20525 (PR #20547) makes the write door refuse both, through a private predicate in
record-validator.ts(namesRealCalendarDay/ISO_DATETIME_WRITE_FORM). The write door is now strictly narrower than the comparand door. #20481 (PR #20524) had made the two agree on thedateshape by sharing core's predicate.Suggested shape (⛔ not a ruling)
readsAsCalendarDay, as a move, and have the comparand door refuse what the write door refuses (INVALID_FILTER/ 400).2028-02-29leap control and an ISO control.Dedupe
search_issues, run by this seat inobjectstack-ai/objectstack, open and closed: "temporal comparand door impossible day 2026-02-30 admitted rolled over non-ISO datetime comparand host timezone" gives 12 hits.2026-02-30is stored verbatim (500 on PostgreSQL), datetime2026-02-30T10:00:00Zrolls over to March 2, and a non-ISO datetime is read in the host zone #20525 is the write-door twin.timecomparand spelled with an extended-ISO year (+010000-01-01T10:00:00Z) is compared as text on memory and SQLite:$gtanswers 3 of 3 rows,$lt0, where the same wall clock as a 2026 instant answers 2 / 1 #20480 is an extended-yeartimecomparand.temporalStorageForm: thedatearm leaves a year outside 1000..9999 unpadded — over REST the epoch-ms number for 0999-06-15 counts$gt0 /$lt7 on InMemoryDriver and SQLite (correct 6 / 0); its ISO string counts 6 / 0 #20240, temporal values outside the years a four-digit text or a backend holds: adatetimecomparand for year 10000 or −1 misorders on memory/SQLite and 500s on PostgreSQL; adatein year 0000 500s on PostgreSQL; adatewrite stores+010000-…verbatim #20264, objectqlhaving: a comparand on an aggregateddatecolumn never meets the temporal-comparand door — over RESThaving { last_placed: { $lt: "not-a-date" } }onmax(placed_on)keeps every group (200) while itswheretwin answers 400 #20263, An unparseable date comparand on a datetime filter is passed through and compares false — HTTP 200, zero rows, no diagnostic — while an unknown{placeholder}is correctly rejected 400 (17.0.0 GA) #8690, record validator: adatefield written as a non-ISO string ("2026/07/15") answers 201 and is stored verbatim as"2026/07/15", a non-day, on memory and SQLite, because thedatearm admits anyDate.parse-readable string #20481 and driver-sql + driver-memory: an epoch-millisecond NUMBER against adatefield is read by neither driver's storage rule —where: { placed_on: { $gt: 1769940000000 } }returns 6 of 6 rows on SqlDriver and 0 on InMemoryDriver over REST #20203 are other temporal classes, all closed.None is this.
Dedupe words:
comparand impossible day 2026-02-30 rolled over·where datetime non-ISO host timezone·isUninterpretableTemporalComparand real calendar day·date comparand 2026-02-30 postgres 500