From 7a2e8a4bdf03ba235bd5ba650f812f1790a22531 Mon Sep 17 00:00:00 2001 From: rhodey Date: Wed, 28 Jan 2026 07:57:02 -0500 Subject: [PATCH 1/3] check that activeQuery is not null every time before use and emit an error if is. --- packages/pg/lib/client.js | 48 ++++++++++++++++++++++++++++++++++----- 1 file changed, 42 insertions(+), 6 deletions(-) diff --git a/packages/pg/lib/client.js b/packages/pg/lib/client.js index df430f881..b0214e3dc 100644 --- a/packages/pg/lib/client.js +++ b/packages/pg/lib/client.js @@ -407,23 +407,47 @@ class Client extends EventEmitter { } _handleRowDescription(msg) { + const activeQuery = this._getActiveQuery() + if (activeQuery == null) { + const error = new Error('Received unexpected rowDescription message from backend.') + this._handleErrorEvent(error) + return + } // delegate rowDescription to active query - this._getActiveQuery().handleRowDescription(msg) + activeQuery.handleRowDescription(msg) } _handleDataRow(msg) { + const activeQuery = this._getActiveQuery() + if (activeQuery == null) { + const error = new Error('Received unexpected dataRow message from backend.') + this._handleErrorEvent(error) + return + } // delegate dataRow to active query - this._getActiveQuery().handleDataRow(msg) + activeQuery.handleDataRow(msg) } _handlePortalSuspended(msg) { + const activeQuery = this._getActiveQuery() + if (activeQuery == null) { + const error = new Error('Received unexpected portalSuspended message from backend.') + this._handleErrorEvent(error) + return + } // delegate portalSuspended to active query - this._getActiveQuery().handlePortalSuspended(this.connection) + activeQuery.handlePortalSuspended(this.connection) } _handleEmptyQuery(msg) { + const activeQuery = this._getActiveQuery() + if (activeQuery == null) { + const error = new Error('Received unexpected emptyQuery message from backend.') + this._handleErrorEvent(error) + return + } // delegate emptyQuery to active query - this._getActiveQuery().handleEmptyQuery(this.connection) + activeQuery.handleEmptyQuery(this.connection) } _handleCommandComplete(msg) { @@ -453,11 +477,23 @@ class Client extends EventEmitter { } _handleCopyInResponse(msg) { - this._getActiveQuery().handleCopyInResponse(this.connection) + const activeQuery = this._getActiveQuery() + if (activeQuery == null) { + const error = new Error('Received unexpected copyInResponse message from backend.') + this._handleErrorEvent(error) + return + } + activeQuery.handleCopyInResponse(this.connection) } _handleCopyData(msg) { - this._getActiveQuery().handleCopyData(msg, this.connection) + const activeQuery = this._getActiveQuery() + if (activeQuery == null) { + const error = new Error('Received unexpected copyData message from backend.') + this._handleErrorEvent(error) + return + } + activeQuery.handleCopyData(msg, this.connection) } _handleNotification(msg) { From a158f035dcf10cb3e64185a12183c184094cd959 Mon Sep 17 00:00:00 2001 From: Charmander <~@charmander.me> Date: Wed, 28 Jan 2026 08:49:29 -0800 Subject: [PATCH 2/3] docs: code style consistency --- docs/pages/index.mdx | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/docs/pages/index.mdx b/docs/pages/index.mdx index 77a410626..ff27662e6 100644 --- a/docs/pages/index.mdx +++ b/docs/pages/index.mdx @@ -44,7 +44,7 @@ The simplest possible way to connect, query, and disconnect is with async/await: ```js import { Client } from 'pg' -const client = await new Client().connect(); +const client = await new Client().connect() const res = await client.query('SELECT $1::text as message', ['Hello world!']) console.log(res.rows[0].message) // Hello world! @@ -55,10 +55,9 @@ await client.end() For the sake of simplicity, these docs will assume that the methods are successful. In real life use, make sure to properly handle errors thrown in the methods. A `try/catch` block is a great way to do so: -```ts +```js import { Client } from 'pg' -const client = new Client() -await client.connect() +const client = await new Client().connect() try { const res = await client.query('SELECT $1::text as message', ['Hello world!']) From 1c640d0b44db333b2e919e30d866a289fa49cabb Mon Sep 17 00:00:00 2001 From: Brian Carlson Date: Thu, 29 Jan 2026 19:59:32 -0600 Subject: [PATCH 3/3] Add more tests --- .../pg/test/integration/gh-issues/3174-tests.js | 6 ++++++ packages/pg/test/test-buffers.js | 16 ++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/packages/pg/test/integration/gh-issues/3174-tests.js b/packages/pg/test/integration/gh-issues/3174-tests.js index 9949c8071..462cb825e 100644 --- a/packages/pg/test/integration/gh-issues/3174-tests.js +++ b/packages/pg/test/integration/gh-issues/3174-tests.js @@ -165,4 +165,10 @@ const testErrorBuffer = (bufferName, errorBuffer) => { if (!helper.args.native) { testErrorBuffer('parseComplete', buffers.parseComplete()) testErrorBuffer('commandComplete', buffers.commandComplete('f')) + testErrorBuffer('rowDescription', buffers.rowDescription()) + testErrorBuffer('dataRow', buffers.dataRow()) + testErrorBuffer('portalSuspended', buffers.portalSuspended()) + testErrorBuffer('emptyQuery', buffers.emptyQuery()) + testErrorBuffer('copyIn', buffers.copyIn(0)) + testErrorBuffer('copyData', buffers.copyData(Buffer.from([1, 2, 3]))) } diff --git a/packages/pg/test/test-buffers.js b/packages/pg/test/test-buffers.js index 576d22f7e..8beee33ec 100644 --- a/packages/pg/test/test-buffers.js +++ b/packages/pg/test/test-buffers.js @@ -118,4 +118,20 @@ buffers.portalSuspended = function () { return new BufferList().join(true, 's') } +buffers.copyIn = function (cols) { + const list = new BufferList() + // text mode + .add(Buffer.from([0])) + // column count + .addInt16(cols) + for (let i = 0; i < cols; i++) { + list.addInt16(i) + } + return list.join(true, 'G') +} + +buffers.copyData = function (bytes) { + return new BufferList().add(bytes).join(true, 'd') +} + module.exports = buffers