Skip to content

fix(pg-cursor): handle exceptions from row type parsers - #3840

Open
IbrahimHafez1 wants to merge 3 commits into
brianc:masterfrom
IbrahimHafez1:codex/cursor-type-parser-errors
Open

IbrahimHafez1 wants to merge 3 commits into
brianc:masterfrom
IbrahimHafez1:codex/cursor-type-parser-errors

Conversation

@IbrahimHafez1

@IbrahimHafez1 IbrahimHafez1 commented Oct 29, 2026 •

Copy link
Copy Markdown

Fixes #3839.

A custom row type parser can throw from pg-cursor's PostgreSQL message handler, escaping an awaited read() and terminating the process. pg-query-stream inherits the same failure. Core client.query() already rejects this kind of parser error normally.

Catch the parser exception and stop parsing further rows in that batch. Close the portal at the suspended/final batch boundary and report the error once after protocol completion. Pending/subsequent reads receive the error; the client remains usable. Preserve the first parser error if a later row also produces a server error. Shared error dispatch clears the active callback before invoking it and reports only once, including when a query timeout precedes protocol completion.

Nine new regression cases cover object/array rows, suspended/final batches, queued reads, callback and promise consumers, async iteration and flowing streams, one error/close notification, portal release, a queued subsequent query, and timeout completion without duplicate error delivery.

Validation on Node 22.23.4 and PostgreSQL 16.15:

  • Original implementation fails the new cursor and stream regressions with uncaught parser errors. A further real-database timeout test reproduced duplicate delivery on the earlier PR head and passes at ca68aec.
  • Full pg-cursor suite: 49 passing.
  • Full pg-query-stream suite: 43 passing.
  • Repository ESLint 10.2.1, Prettier 3.0.3 and diff checks pass.
  • Source and new stream tests pass TypeScript 6.0.3 checks with the repository's types. The three stream regressions also pass using normal ts-node/register with type checking enabled. Tests use the typed stream.callback property to support the repository's older pg typings.
  • The full stream runtime suite uses transpile-only: full typed execution hits an existing unused @ts-expect-error in test/client-options.ts; the new parser regressions and source type-check separately.
  • No manifest or lockfile changes. Other monorepo package suites were not rerun.

There is no new SQL or successful-row allocation. Error containment adds a guard and try/catch to the existing parse operation. Local warmed 100k-row microbenchmarks varied between runs (6.34→6.64ms and 7.25→5.31ms); these do not establish a reliable speedup or end-to-end performance guarantee.

Current code and related open/closed reports were checked. The timeout, close, concurrent-read and core-query proposals mentioned in the issue address different paths. Exceptions thrown by application event listeners are outside this change.

AI assistance was used for investigation, implementation and review.

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.

pg-cursor type parser exceptions escape read error handling and crash Node

1 participant