Skip to content

fix(pg): throw on invalid Date instead of serializing NaN string#3657

Closed
terminalchai wants to merge 1 commit intobrianc:masterfrom
terminalchai:fix/invalid-date-serialization
Closed

fix(pg): throw on invalid Date instead of serializing NaN string#3657
terminalchai wants to merge 1 commit intobrianc:masterfrom
terminalchai:fix/invalid-date-serialization

Conversation

@terminalchai
Copy link
Copy Markdown

Summary

Fixes #3318

Problem

Passing an invalid Date (e.g.
ew Date(undefined) or
ew Date('not a date')) to a query currently produces the string '0NaN-NaN-NaNTNaN:NaN:NaN.NaN+NaN:NaN'\ which Postgres cannot parse in any useful way, resulting in a confusing server-side error far from the real problem.

\\js
// before
client.query('SELECT ::timestamptz', [new Date(undefined)])
// → sends literal string '0NaN-NaN-NaNTNaN:NaN:NaN.NaN+NaN:NaN' to Postgres
\\

Root cause

In \packages/pg/lib/utils.js, \prepareValue()\ detects \Date\ objects via \isDate(val)\ and immediately passes them to \dateToString()\ / \dateToStringUTC(). Those functions call \date.getFullYear(), \date.getMonth(), etc., which all return \NaN\ for an invalid Date. \String(NaN).padStart(2, '0')\ produces 'NaN', so the resulting timestamp string is garbage.

Fix

Add an \isNaN(val.getTime())\ guard at the top of the \isDate\ branch and throw a clear error:

\\js
if (isDate(val)) {
if (isNaN(val.getTime())) {
throw new Error('date is invalid')
}
// ...
}
\\

\\js
// after
client.query('SELECT ::timestamptz', [new Date(undefined)])
// → throws Error: date is invalid ← caught immediately in JS
\\

Tests

Added two tests to \packages/pg/test/unit/utils-tests.js:

  • \prepareValues: invalid date throws an error\ — covers
    ew Date(undefined)\
  • \prepareValues: invalid date (NaN) does not produce NaN string\ — covers
    ew Date('not a date')\

All existing date tests continue to pass.

new Date(undefined) and new Date('invalid') produce an invalid Date
object whose getTime() returns NaN.  Previously prepareValue() would
pass such a date straight through to dateToString() / dateToStringUTC()
which format each NaN component with padStart(), producing the
meaningless string '0NaN-NaN-NaNTNaN:NaN:NaN.NaN+NaN:NaN' that Postgres
cannot parse.

Add an isNaN(val.getTime()) guard in the isDate branch of prepareValue()
and throw an informative error immediately, so callers discover the bug
at the JS level rather than receiving a cryptic Postgres error.

Fixes brianc#3318
@charmander charmander closed this Apr 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Do not serialize new Date(undefined) as "0NaN-NaN-NaNTNaN:NaN:NaN.NaN+NaN:NaN"

2 participants