Filing gate: ① a product defect with a measured reach:. Finding class (a). reach: is GET /api/v1/data/:object/export followed by POST /api/v1/data/:object/import of that same file. The #20671 dev measured it at PR #20721's head 9b426f8ab on memory, SQLite and a live PostgreSQL 16, under TZ=America/New_York (os-dev-report 5899533181 on #20671, out_of_scope_findings[1]). This PR does not touch the import reader. The readings are the dev's; the seat re-read the named code on origin/main, not the runs.
Filed by the domain:engine execution seat 1 (session_01DEvba2nBuD4tWzfq8r8NFY, os-support-ai). ⛔ Filed bare: routing and grading belong to triage. ⛔ Not a claim. Reader: triage, then the seat of the lane that owns /import (its siblings #20534 and #20602 carry domain:cli).
What happens
- A
time field stored as 10:00:00.250 is accepted by the write door (201) and reads back as 10:00:00.250.
/export writes that cell as 10:00:00.250.
- Re-importing the exported file fails that row with code
invalid_date and Clock: "10:00:00.250" is not a valid time. This happens on all three backends.
So any time with milliseconds is lost on the export, then re-import round trip. The row is refused, not stored wrong.
Why (read on origin/main)
packages/rest/src/import-coerce.ts:273 defines TIME_OF_DAY = /^([01]\d|2[0-3]):[0-5]\d(:[0-5]\d)?$/, which has no fractional part. Its time arm (:506) accepts only that shape. The ISO and year-first readers need a date. The platform's time storage form keeps a .fff suffix when the milliseconds are non-zero (content/docs/protocol/objectql/types.mdx, "Storage format"), and the write door admits it.
Scope for whoever takes it
Dedupe
search_issues in objectstack-ai/objectstack, open and closed:
Dedupe words: import time cell milliseconds refused · export re-import round trip time fraction · import-coerce TIME_OF_DAY fraction
Generated by Claude Code
Filing gate: ① a product defect with a measured
reach:. Finding class (a).reach:isGET /api/v1/data/:object/exportfollowed byPOST /api/v1/data/:object/importof that same file. The #20671 dev measured it at PR #20721's head9b426f8abon memory, SQLite and a live PostgreSQL 16, underTZ=America/New_York(os-dev-report5899533181 on #20671,out_of_scope_findings[1]). This PR does not touch the import reader. The readings are the dev's; the seat re-read the named code onorigin/main, not the runs.Filed by the
domain:engineexecution seat 1 (session_01DEvba2nBuD4tWzfq8r8NFY,os-support-ai). ⛔ Filed bare: routing and grading belong to triage. ⛔ Not a claim. Reader: triage, then the seat of the lane that owns/import(its siblings #20534 and #20602 carrydomain:cli).What happens
timefield stored as10:00:00.250is accepted by the write door (201) and reads back as10:00:00.250./exportwrites that cell as10:00:00.250.invalid_dateandClock: "10:00:00.250" is not a valid time. This happens on all three backends.So any
timewith milliseconds is lost on the export, then re-import round trip. The row is refused, not stored wrong.Why (read on
origin/main)packages/rest/src/import-coerce.ts:273definesTIME_OF_DAY = /^([01]\d|2[0-3]):[0-5]\d(:[0-5]\d)?$/, which has no fractional part. Itstimearm (:506) accepts only that shape. The ISO and year-first readers need a date. The platform'stimestorage form keeps a.fffsuffix when the milliseconds are non-zero (content/docs/protocol/objectql/types.mdx, "Storage format"), and the write door admits it.Scope for whoever takes it
/importreads what/exportwrites for atimecell, fractional seconds included, as /import: parseDateCell emits adatecell year below 1000 unpadded (0500-01-01→500-01-01), so after PR #20524 a valid ISO date cell is refused per row asinvalid_date, and before it a non-day was stored #20534 did for thedateyear.10:00:00control, which already round-trips.Dedupe
search_issuesinobjectstack-ai/objectstack, open and closed:/exportwrites adate/datetimecell with a year below 1000 unpadded (0500-01-01→500-01-01), so the export does not re-import #20602 (the/exportyear padding, open) and /import: parseDateCell emits adatecell year below 1000 unpadded (0500-01-01→500-01-01), so after PR #20524 a valid ISO date cell is refused per row asinvalid_date, and before it a non-day was stored #20534 (the/importdateyear, closed). Neither is thetimefraction.Dedupe words:
import time cell milliseconds refused·export re-import round trip time fraction·import-coerce TIME_OF_DAY fractionGenerated by Claude Code