Repository: brianc/node-postgres (language: javascript)

Issue:
TypeError: Cannot read properties of undefined (reading 'prepareValue')
Hi, 
Latest PR: https://github.com/brianc/node-postgres/commit/940479bc4b601a89a6fc915be959ca96e83dd4d0 broke our runtime completely.
This occurred even though we did not upgrade the version of pg so it was a complete surprise.

Issue is coming from: https://github.com/brianc/node-postgres/blob/940479bc4b601a89a6fc915be959ca96e83dd4d0/packages/pg-cursor/index.js#L4

```
TypeError: Cannot read properties of undefined (reading 'prepareValue')
    at Object.<anonymous> (/<path>/node_modules/pg-cursor/index.js:4:23)
    at Module._compile (node:internal/modules/cjs/loader:1565:14)
    at node:internal/modules/cjs/loader:1708:10
    at Object.require.extensions.<computed> [as .js] (/<path>/node_modules/ts-node/src/index.ts:1608:43)
    at Module.load (node:internal/modules/cjs/loader:1318:32)
    at Function._load (node:internal/modules/cjs/loader:1128:12)
    at TracingChannel.traceSync (node:diagnostics_channel:322:14)
    at wrapModuleLoad (node:internal/modules/cjs/loader:219:24)
    at Module.require (node:internal/modules/cjs/loader:1340:12)
    at require (node:internal/modules/helpers:138:16)
```


Please look into it as soon as possible.
pg version: 8.14.1
node version: 22.12.0
npm version: 10.9.0

Let me know if you need any other details.



Discussion / hints:
Upgrading to latest pg version v8.15.1 might resolve the issue, currently still validating.
But please reconsider this change as **BREAKING CHANGE**, that is not backwards compatible.

> This occurred even though we did not upgrade the version of pg so it was a complete surprise.

This could happen if you are using something with `npx` and `pg` as dependency, some people have reported this problem to me, it occurs because `npx` uses the latest version when it is not pinned.
> Let me know if you need any other details.

I need steps to reproduce your issue in its entirety. A stack-trace can sometimes be enough but in this case...how do you produce that stack trace?
> Upgrading to latest pg version v8.15.1 might resolve the issue, currently still validating. But please reconsider this change as **BREAKING CHANGE**, that is not backwards compatible.

It wasn’t intended to be a breaking change; it’s just a bug, and fixing bugs in patch versions is the right thing to do. You should use a lockfile, by the way.
> > Let me know if you need any other details.
> 
> I need steps to reproduce your issue in its entirety. A stack-trace can sometimes be enough but in this case...how do you produce that stack trace?

This was reproduced when running npm install using pg version: 8.14.1 and the lockfile contained pg-cursor 2.14.1.
When starting the application, using Express for example, this error would be thrown.




> > Upgrading to latest pg version v8.15.1 might resolve the issue, currently still validating. But please reconsider this change as **BREAKING CHANGE**, that is not backwards compatible.
> 
> It wasn’t intended to be a breaking change; it’s just a bug, and fixing bugs in patch versions is the right thing to do. You should use a lockfile, by the way.

If this change was not intended then of course it is a bug, no question. My comment was aiming to let the owner or whoever made the change know that if it is intended then add it as a new version and not just a patch version.


> Upgrading to latest pg version v8.15.1 might resolve the issue, currently still validating.

Using version 8.15.1 resolved the issue for me.


EDIT: testing again older versions as I still see an issue there. I'll try to create a reproducible snippet
EDIT2: Okay, managed to reproduce it with pg-query-stream as it imports pg-cursor internally.
EDIT3: updated example with pg-query-stream to latest 4.9.5, but still same issue.
package.json
```json
{
  "name": "pg-test",
  "version": "1.0.0",
  "main": "index.js",
  "scripts": {
    "start": "node index.js"
  },
  "author": "Immanuel",
  "license": "ISC",
  "description": "",
  "dependencies": {
    "pg": "8.14.1",
    "pg-query-stream": "4.9.5"
  },
  "engines":     {
    "node": "22.x.x",
    "npm": ">=10.x.x"
  }
}
```
index.js
```
const { Pool } = require('pg');
const QueryStream = require('pg-query-stream');

const pool = new Pool({
    user: 'user',
    password: 'pass',
    database: 'database',
    host: 'localhost',
    port: 5432,
});
(async () => {
    const dbClient = await pool.connect();
    const queryStream = new QueryStream('SELECT NOW()');
    dbClient.query(queryStream);
})()

```

Hope this helps.
A colleague suggested a quick solution/workaround for cases where a version update is not possible.
Adding this to the package.json should resolve the issue, at least it did for the example above.
```json
"overrides": {
    "pg-cursor": "2.11.0"
  },
```
I think I understand it now.

the #2353 PR made changes to the `pg-cursor` package, specifically this:
https://github.com/brianc/node-postgres/blob/940479bc4b601a89a6fc915be959ca96e83dd4d0/packages/pg-cursor/index.js#L2-L4

it was like this before:
https://github.com/brianc/node-postgres/blob/81ec0635fc1836c99b5975a8225ce6ede901e7d5/packages/pg-cursor/index.js#L2-L3

and `pg-cursor` package (a few other packages too actually) got this peer dependency:
https://github.com/brianc/node-postgres/blob/940479bc4b601a89a6fc915be959ca96e83dd4d0/packages/pg-cursor/package.json#L30-L32

That's why all previous versions broke, because from minor `8.15.x`, the path of import/require changed, and with the peer dependency fixed at `8^`, `pg-cursor` will always come with the latest minor/patch, which no longer supports that form of import.

EDIT:

Ok, I've been thinking for a while, and I’ve decided not to open a PR since it ultimately depends on what @brianc wants to do, there are a few possible ways to fix it.

For either of the options below (or even another one), it might also be a good idea to start pinning major and minor versions in peer dependencies across packages, to avoid issues in future releases.

### First option

Apply a workaround at  
https://github.com/brianc/node-postgres/blob/940479bc4b601a89a6fc915be959ca96e83dd4d0/packages/pg-cursor/index.js#L2-L4

Modify it like this so both older and newer versions of `pg` work:

```js
const pg = require('pg')
const Result = pg.Result || require('pg/lib/result.js')
const prepare = (pg.utils && pg.utils.prepareValue) || require('pg/lib/utils.js').prepareValue
```

Then deprecate this approach in a future major release.

### Second option

Revert all ESM-related changes and release a new `8.15.6` or `8.16.0` version, then reintroduce the ESM changes in a new `9.0.0`.  
This way, older packages such as `pg-cursor` depending on `"pg": "^8"` won’t break unexpectedly.

### Third option

Advise users to apply the override workaround when using packages that depend on older `pg` internals.
ah i see if `pg-cursor` has a peer dep on pg@8.x i should bump the peer dep to pg@8.15.5 and we should be good to go. I can take care of that! ty

note: I thought learna would take care of this automatically...apparently not
> ah i see if `pg-cursor` has a peer dep on pg@8.x i should bump the peer dep to pg@8.15.5 and we should be good to go. I can take care of that! ty
> 
> note: I thought learna would take care of this automatically...apparently not

I'm not sure that just bumping the peer dependency to `pg@8.15.5` is the right fix here. Using `pg@8.15.5` with the latest `pg-cursor` works fine, and has been working since `pg@8.15.1`.

The real issue is when someone uses `pg-cursor` with an older version of pg (like `8.14.x` or earlier). In that case, `pg-cursor` ends up downloading the latest `pg@^8`, which brings in the ESM changes and breaks things because older versions use another way for imports.

So the breakage happens when `pg-cursor` is installed alongside an older pg, not the other way around.

Example
If I open an old repo, which uses  pg 8.14.x and `pg-cursor` of any previous version, after running `npm install`, old `pg-cursor` will come with pg `8.15.x` since it takes ^8.x.x and everything will fail, That's probably what happened.

Yah your right, read it wrong pre-coffee this morning. I have an idea for a
fix…stand by for a few hrs and i might have something for you!

On Thu, Apr 24, 2025 at 11:59 AM Breno A. ***@***.***> wrote:

> *brenoepics* left a comment (brianc/node-postgres#3430)
> <https://github.com/brianc/node-postgres/issues/3430#issuecomment-2828282900>
>
> ah i see if pg-cursor has a peer dep on ***@***.*** i should bump the peer dep
> to ***@***.*** and we should be good to go. I can take care of that! ty
>
> note: I thought learna would take care of this automatically...apparently
> not
>
> I'm not sure that bumping the peer dependency to ***@***.*** is the right
> fix here. Using ***@***.*** with the latest pg-cursor works fine, and has
> been working since ***@***.***
>
> The real issue is when someone uses pg-cursor with an older version of pg
> (like 8.14.x or earlier). In that case, pg-cursor ends up downloading the
> latest pg@^8, which brings in the ESM changes and breaks things because
> older versions use another way for imports.
>
> So the breakage happens when pg-cursor is installed alongside an older
> pg, not the other way around.
>
> —
> Reply to this email directly, view it on GitHub
> <https://github.com/brianc/node-postgres/issues/3430#issuecomment-2828282900>,
> or unsubscribe
> <https://github.com/notifications/unsubscribe-auth/AAAMHIPBBUJPIWKNY4VEBZ323EJ7LAVCNFSM6AAAAAB3VV7HU2VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDQMRYGI4DEOJQGA>
> .
> You are receiving this because you were mentioned.Message ID:
> ***@***.***>
>

> Yah your right, read it wrong pre-coffee this morning. I have an idea for a
> fix…stand by for a few hrs and i might have something for you!
> […](#)

waiting for it as well, thanks! ^ 🤞 

Fix patch:
diff --git a/packages/pg-cursor/index.js b/packages/pg-cursor/index.js
index 8ee481305..f1553cc9c 100644
--- a/packages/pg-cursor/index.js
+++ b/packages/pg-cursor/index.js
@@ -1,7 +1,7 @@
 'use strict'
-const pg = require('pg')
-const { Result, utils } = pg
-const prepare = utils.prepareValue
+// note: can remove these deep requires when we bump min version of pg to 9.x
+const Result = require('pg/lib/result.js')
+const prepare = require('pg/lib/utils.js').prepareValue
 const EventEmitter = require('events').EventEmitter
 const util = require('util')
 


Test patch: