Summary
The write side of @db.Time is broken in 3.6.x. When a JS Date is sent to a @db.Time column, the underlying kysely pg driver serializes the parameter as the ISO datetime returned by Date.prototype.toISOString() (e.g. \"2026-04-29T21:00:00.000Z\"). Postgres TIME columns reject the string with:
error: invalid input syntax for type time: \"2026-04-29T21:00:00.000Z\"
code: 22007
This is the write-side counterpart to #2590 (which fixed @db.Time reads silently returning raw strings).
Repro
model Parent {
id String @id @default(uuid())
children Child[]
}
model Child {
id String @id @default(uuid())
parentId String
open DateTime @db.Time(6)
close DateTime @db.Time(6)
parent Parent @relation(fields: [parentId], references: [id])
}
await db.parent.create({
data: {
children: {
createMany: {
data: [{
open: new Date('1970-01-01T09:00:00Z'),
close: new Date('1970-01-01T16:00:00Z'),
}],
},
},
},
});
The validator (after #2632) accepts the Date, but the resulting INSERT throws 22007.
What I think is happening
@zenstackhq/orm builds the query through kysely's pg dialect. Kysely's parameter binding is column-type-agnostic by design — when given a Date, it serializes via the standard pg-types path which produces an ISO timestamp string. Postgres' TIME column type rejects ISO timestamp input; it expects HH:MM:SS (with optional fractional seconds and timezone offset).
For @db.Date and @db.Timestamp this isn't a problem — Postgres accepts the ISO string for both. Only TIME is strict.
Suggested fix
Either:
- Pre-serialize at the ZenStack input layer for
@db.Time columns: detect the column's native type and convert the Date (or string) into HH:MM:SS before kysely builds the query.
- Pre-serialize at the dialect layer: extend
PostgresCrudDialect to wrap Date parameters bound to TIME columns with a sql.lit(...) value formatted as TIME.
- Document & expose a helper for users to opt into manual TIME formatting (similar to how
@db.Bytes requires explicit Uint8Array).
Option 1 keeps the user surface unchanged — they pass a Date (or, after #2632, an ISO time-only string) and the query just works. Happy to send a PR if there's interest.
Workaround we're using
Migrating our TIME columns to TIMESTAMP. The application only reads time-of-day from the field anyway, so the date prefix is harmless. Not viable for users who genuinely need TIME semantics (range queries, etc.).
Versions
@zenstackhq/orm: 3.6.4
prisma: 7.8.0
kysely: 0.28.16
pg: 8.20.0
node: 22.x
Summary
The write side of
@db.Timeis broken in 3.6.x. When a JSDateis sent to a@db.Timecolumn, the underlying kysely pg driver serializes the parameter as the ISO datetime returned byDate.prototype.toISOString()(e.g.\"2026-04-29T21:00:00.000Z\"). Postgres TIME columns reject the string with:This is the write-side counterpart to #2590 (which fixed
@db.Timereads silently returning raw strings).Repro
The validator (after #2632) accepts the
Date, but the resulting INSERT throws22007.What I think is happening
@zenstackhq/ormbuilds the query through kysely's pg dialect. Kysely's parameter binding is column-type-agnostic by design — when given aDate, it serializes via the standard pg-types path which produces an ISO timestamp string. Postgres' TIME column type rejects ISO timestamp input; it expectsHH:MM:SS(with optional fractional seconds and timezone offset).For
@db.Dateand@db.Timestampthis isn't a problem — Postgres accepts the ISO string for both. Only TIME is strict.Suggested fix
Either:
@db.Timecolumns: detect the column's native type and convert theDate(or string) intoHH:MM:SSbefore kysely builds the query.PostgresCrudDialectto wrapDateparameters bound to TIME columns with asql.lit(...)value formatted as TIME.@db.Bytesrequires explicitUint8Array).Option 1 keeps the user surface unchanged — they pass a
Date(or, after #2632, an ISO time-only string) and the query just works. Happy to send a PR if there's interest.Workaround we're using
Migrating our TIME columns to TIMESTAMP. The application only reads time-of-day from the field anyway, so the date prefix is harmless. Not viable for users who genuinely need TIME semantics (range queries, etc.).
Versions
@zenstackhq/orm: 3.6.4prisma: 7.8.0kysely: 0.28.16pg: 8.20.0node: 22.x