sequelize: Error: Cannot find module 'pg-native'

Exception occurs when trying to add two (or more) equal values in a unique field using findOrCreate.

Test code:

var arr = [0, 1];

var User = sequelize.define('User', {
    login: {
        type: Sequelize.STRING,
        unique: true
    }
});

User.sync({ force: true })
.then(function () {
    sequelize.transaction()
    .then(function (tx) {
        return Promise.map(arr, function () {
            return User.findOrCreate({
                where: {
                    login: 'test'
                },
                transaction: tx
            });
        })
        .then(function () {
            tx.commit();
        });
    });
});

SQL log:

Executing (default): DROP TABLE IF EXISTS "Users" CASCADE;
Executing (default): CREATE TABLE IF NOT EXISTS "Users" ("id"   SERIAL , "login" VARCHAR(255) UNIQUE, PRIMARY KEY ("id"));
Executing (default): SELECT i.relname AS name, ix.indisprimary AS primary, ix.indisunique AS unique, ix.indkey AS indkey, array_agg(a.attnum) as column_indexes, array_agg(a.attname) AS column_names, pg_get_indexdef(ix.indexrelid) AS definition FROM pg_class t, pg_class i, pg_index ix, pg_attribute a WHERE t.oid = ix.indrelid AND i.oid = ix.indexrelid AND a.attrelid = t.oid AND a.attnum = ANY(ix.indkey) AND t.relkind = 'r' and t.relname = 'Users' GROUP BY i.relname, ix.indexrelid, ix.indisprimary, ix.indisunique, ix.indkey ORDER BY i.relname;
Executing (6a28eaa0-9716-4db0-be66-967f8ec12058): START TRANSACTION;
Executing (6a28eaa0-9716-4db0-be66-967f8ec12058): SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
Executing (6a28eaa0-9716-4db0-be66-967f8ec12058): SET autocommit = 1;
Executing (6a28eaa0-9716-4db0-be66-967f8ec12058): SAVEPOINT "6a28eaa0-9716-4db0-be66-967f8ec12058-savepoint-1";
Executing (6a28eaa0-9716-4db0-be66-967f8ec12058): SAVEPOINT "6a28eaa0-9716-4db0-be66-967f8ec12058-savepoint-2";
Executing (6a28eaa0-9716-4db0-be66-967f8ec12058): SELECT "id", "login" FROM "Users" AS "User" WHERE "User"."login" = 'test' LIMIT 1;
Executing (6a28eaa0-9716-4db0-be66-967f8ec12058): SELECT "id", "login" FROM "Users" AS "User" WHERE "User"."login" = 'test' LIMIT 1;
Executing (6a28eaa0-9716-4db0-be66-967f8ec12058): CREATE OR REPLACE FUNCTION pg_temp.testfunc(OUT response "Users", OUT sequelize_caught_exception text) RETURNS RECORD AS $func_66f952b0ec354cdbb8923433f3248e4a$ BEGIN INSERT INTO "Users" ("id","login") VALUES (DEFAULT,'test') RETURNING * INTO response; EXCEPTION WHEN unique_violation THEN GET STACKED DIAGNOSTICS sequelize_caught_exception = PG_EXCEPTION_DETAIL; END $func_66f952b0ec354cdbb8923433f3248e4a$ LANGUAGE plpgsql; SELECT (testfunc.response).*, testfunc.sequelize_caught_exception FROM pg_temp.testfunc(); DROP FUNCTION IF EXISTS pg_temp.testfunc();
Executing (6a28eaa0-9716-4db0-be66-967f8ec12058): CREATE OR REPLACE FUNCTION pg_temp.testfunc(OUT response "Users", OUT sequelize_caught_exception text) RETURNS RECORD AS $func_2abdfe30c027469dac0b5fe594fb4dda$ BEGIN INSERT INTO "Users" ("id","login") VALUES (DEFAULT,'test') RETURNING * INTO response; EXCEPTION WHEN unique_violation THEN GET STACKED DIAGNOSTICS sequelize_caught_exception = PG_EXCEPTION_DETAIL; END $func_2abdfe30c027469dac0b5fe594fb4dda$ LANGUAGE plpgsql; SELECT (testfunc.response).*, testfunc.sequelize_caught_exception FROM pg_temp.testfunc(); DROP FUNCTION IF EXISTS pg_temp.testfunc();

Error stack:

Unhandled rejection Error: Cannot find module 'pg-native'
    at Function.Module._resolveFilename (module.js:336:15)
    at Function.Module._load (module.js:278:25)
    at Module.require (module.js:365:17)
    at require (module.js:384:17)
    at Object.<anonymous> (/home/user/test/node_modules/pg/lib/native/index.js:1:76)
    at Module._compile (module.js:460:26)
    at Object.Module._extensions..js (module.js:478:10)
    at Module.load (module.js:355:32)
    at Function.Module._load (module.js:310:12)
    at Module.require (module.js:365:17)
    at require (module.js:384:17)
    at null.<anonymous> (/home/user/test/node_modules/pg/lib/index.js:78:36)
    at /home/user/test/node_modules/lodash/index.js:3159:32
    at baseForOwn (/home/user/test/node_modules/lodash/index.js:2089:14)
    at baseClone (/home/user/test/node_modules/lodash/index.js:1799:39)
    at /home/user/test/node_modules/lodash/index.js:1800:23
From previous event:
    at Promise.catch (/home/user/test/node_modules/sequelize/lib/promise.js:21:17)
    at Object.<anonymous> (/home/user/test/node_modules/sequelize/lib/model.js:1199:15)
From previous event:
    at Promise.then (/home/user/test/node_modules/sequelize/lib/promise.js:21:17)
    at module.exports.Model.findOrCreate (/home/user/test/node_modules/sequelize/lib/model.js:1180:8)
    at /home/user/test/tests.js:30:16
From previous event:
    at /home/user/test/tests.js:29:18
    at processImmediate [as _immediateCallback] (timers.js:358:17)
From previous event:
    at Promise.then (/home/user/test/node_modules/sequelize/lib/promise.js:21:17)
    at Object.<anonymous> (/home/user/test/tests.js:26:2)
    at Module._compile (module.js:460:26)
    at Object.Module._extensions..js (module.js:478:10)
    at Module.load (module.js:355:32)
    at Function.Module._load (module.js:310:12)
    at Function.Module.runMain (module.js:501:10)
    at startup (node.js:129:16)
    at node.js:814:3

Note: without the transaction is the same error

About this issue

  • Original URL
  • State: closed
  • Created 9 years ago
  • Reactions: 4
  • Comments: 69 (19 by maintainers)

Commits related to this issue

Most upvoted comments

The error occurs when calling optClone->lodash.cloneDeep from findOne and other similar methods. The PG-module has a property ‘native’, which is a getter:

module.exports.__defineGetter__("native", function() {
  delete module.exports.native;
  module.exports.native = new PG(require('./native'));
  return module.exports.native;
});

During cloning this getter is called and throwing error.

Workarounds:

1: Before Sequelize initialization in application we can remove stupid getter:

var pg = require('pg');
delete pg.native;

It should be documented.

2: Delete getter when require PG in Sequelize connection-manager.js if config.native === false

3: Or we need to patch Units.clone for totally skipping property ‘lib’ cloning:

   cloneDeep: function(obj, fn) {
-    return lodash.cloneDeep(obj, function (elem) {
+    return lodash.cloneDeep(obj, function (elem, key) {
+      // Skip property 'lib' cloning (PG-native error workaround)
+      if (key === 'lib' && elem.hasOwnProperty('native')) {
+        return elem;
+      }
+

Hi there!

It just happened to me as well but I found why 😉

So first the delete pg.native; didn’t work for me.

What happened in my case is that I have winston as a logger and I was doing something like logger.debug({'fontFromDb': fontFromDb}). The logger tries to log everything and call this getter that shouldn’t be called and 💥

So make sure you don’t have anything like a clone or a logger on an instance. If you need to clone or log do it with a raw: true query that returns a JSON or turn the instance to JSON like this: fontFromDb.toJSON()

I have this problem in 4.37.10 too.

I’ve found the exact line of code which triggers this error me, it’s when I’m comparing a non-persistent Sequelize instance with a regular object using: expect(myObject).to.deep.equal(mySequelizeInstance);, where expect is defined as const { expect } = require('chai');.

I guess the problem arises when Chai’s deep-eql tries to inspect the native getter, or something similar. I get the same problem if I use lodash’s cloneDeep on a Sequelize instance.

So if you have code that inspects/clones a Sequelize instance you could be faced with this problem. For me the workaround was just to make sure that I got a plain object using the instance’s method toJSON before doing any kind of inspection or cloning.

same in version 4.37.6. Please reopen this bug.

Just a word. This issue is 4,5 years ago. I think one could expect a little more than an obscure an not-always-working workaround to fix an issue on a ORM, IMHO. Just to say

Please, This issue is about sequelize models / transactions / whatever-objects messing up with whatever-logging strategy.

Maybe we should try not to polute this thread with workarounds for every-loggers-on-earth. At the end of the day, console.log(sequelizeModel) just messes; the issue is about fixing that.

@superrandres you have pg@7.14.0. Try using pg@8 or above (npm i -s pg@8) and see if the error is still there. I indicated a few post ago that upgrading pg from 7 to 8 solved the issue for me.

From the looks of it, the workaround by tornillo should work for everyone.

const pg = require('pg');
delete pg.native;

Since version 8, the .native getter is no longer enumerable, therefore this problem can be avoided by upgrading to pg 8. For this reason I will close this issue now. If anyone still experiences this problem with pg 8 please let me know and I will reopen this.

However, in principle, it is Sequelize’s fault to deep clone these things to begin with. I’ve opened #13168 to track this.

pg@8 has been released, which contains a (hopefully) fix for this. Is it safe to upgrade though?.. I just ran npm i -s pg@8 and my very basic routes seem to be working fine…

So after reading pg module code, I found that problem with bundling is in index.js file:

if (typeof process.env.NODE_PG_FORCE_NATIVE !== 'undefined') {
  module.exports = new PG(require('./native'))
} else {
  module.exports = new PG(Client)

  // lazy require native module...the native module may not have installed
  module.exports.__defineGetter__('native', function () {
    delete module.exports.native
    var native = null
    try {
      native = new PG(require('./native'))
    } catch (err) {
      if (err.code !== 'MODULE_NOT_FOUND') {
        throw err
      }
      /* eslint-disable no-console */
      console.error(err.message)
      /* eslint-enable no-console */
    }
    module.exports.native = native
    return native
  })

It requires ./native file which is depending on pg-native. So to pack it with webpack we need to ignore this import. To do it just use webpack.IgnorePlugin:

new webpack.IgnorePlugin(/.\/native/),

After this addition, everything works fine.

@jamiesoncj I have the same issue as you and managed to workaround that by changing

    logging: logger.debug.bind(logger),

to

    logging: sql => logger.debug(sql),

No idea why it works, kinda makes no sense.

For me, this error occurred when I tried to put Sequelize instance inside of a Winston logger.

logger.info('getSegmentData', { lastAttempt, previousAttempt });

Fix:

logger.info('getSegmentData', { 
    lastAttempt: lastAttempt ? lastAttempt.get({ plain: true }) : null,
    previousAttempt: previousAttempt ? previousAttempt.get({ plain: true }) : null
});

@1valdis Hmmm, thanks for pinging, I will look into it later

If the failure happens at build time (e.g. when running webpack), and you don’t want to use pg-native, you can add it to webpack’s externals s.t. it doesn’t complain if it can’t find the package.

@papb I’ve been using pg@8 with Sequelize 5 for a month, having Winston as logger, and made a production app on the combo without ever encountering cannot find module 'pg-native'. Can you confirm that? In fact, nothing has broken in Sequelize 5 with pg@8 (and pg changelog suggested there are only very subtle breaking changes), so I think my upgrade was totally worth it.

@anistark I think you answered your own question 😅 hopefully it will be fixed as a side-effect of #11832

Just to add that I see this issue when trying to use the Winston logger too - for example as shown below. Haven’t found an issue in the Winston repo yet.


const transports = [
  new winston.transports.Console({
    json: true,
    colorize: true,
    handleExceptions: true,
    humanReadableUnhandledException: true,
  }),
];

const logger = winston.createLogger({
  level: 'debug',
  transports,
});

const sequelize = new Sequelize(config.databaseUrl, {
    logging: logger.debug.bind(logger),
    dialect: 'postgres',
    pool: {
      max: 5,
      min: 0,
      idle: 10000,
    },
    protocol: 'postgres',
    dialectOptions: {
      ssl: true,
    },
  });

As AlariCode said:

So after reading pg module code, I found that problem with bundling is in index.js file

This is a problem with pg, not Sequelize, and it’s being worked on very recently: see node-postgres#1894 and node-postgres#1992.

From the looks of it, the workaround by tornillo should work for everyone.

const pg = require('pg');
delete pg.native;

Fixed this by not installing pg-native module and sequelize config:

var db = new Sequelize(..., {
  "dialect": "postgres",
  "native": false
});

Made some research about performance drawbacks and found nothing.