question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

queryInterface.upsert fails, reading 'primaryKeys' of undefined

See original GitHub issue

Issue Creation Checklist

  • I understand that my issue will be automatically closed if I don’t fill in the requested information
  • I have read the contribution guidelines

Bug Description

When using queryInterface.upsert in a seed file, records are not updated on conflict, but instead an error is thrown: ERROR: Cannot read properties of undefined (reading 'primaryKeys')

Reproducible Example

Here is the link to the SSCCE for this issue: https://github.com/Jdmorrisett/sequelize-demo

  • Apply all migrations
    • sequelize db:migrate
  • Apply the first seed file (20220804024548-my-seed-file) and attempt to apply the issue seed file (20220804025436-issue-with-upsert) and observe the issue
    • sequelize db:seed --seed 20220804024548-my-seed-file.js 20220804025436-issue-with-upsert.js
let insertValues = [
      {
        first_name: "John",
        last_name: "Doe",
        bio: "I just updated my profile again",
        createdAt: new Date(),
        updatedAt: new Date(),
        email: "johnDoe@test.com",
      },
      {
        first_name: "Jane",
        last_name: "Doe",
        bio: "I am a new user to this application",
        createdAt: new Date(),
        updatedAt: new Date(),
        email: "janeDoe@test.com",
      },
    ];

    // https://sequelize.org/api/v6/class/src/dialects/abstract/query-interface.js~queryinterface#instance-method-upsert
    // ERROR: Cannot read properties of undefined (reading 'primaryKeys')
    for (let values of insertValues)
      await queryInterface.upsert(
        "Users",
        values,
        {
          bio: values.bio,
          email: values.email,
          updatedAt: values.updatedAt,
        },
        { first_name: values.first_name, last_name: values.last_name }
      );
  },

What do you expect to happen?

I expect the bio, email, and updatedAt fields to be updated on the record for “John Doe” User in the database, and for User “Jane Doe” to be inserted.

What is actually happening?

The “John Doe” user isn’t updated and an error is thrown: ERROR: Cannot read properties of undefined (reading 'primaryKeys')

Environment

  • Sequelize version: 6.21.3
  • Node.js version: v16.14.0
  • If TypeScript related: TypeScript version:
  • Database & Version: PostgreSQL 13
  • Connector library & Version: pg v8.7.3

Would you be willing to resolve this issue by submitting a Pull Request?

  • Yes, I have the time and I know how to start.
  • Yes, I have the time but I will need guidance.
  • No, I don’t have the time, but my company or I are supporting Sequelize through donations on OpenCollective.
  • No, I don’t have the time, and I understand that I will need to wait until someone from the community or maintainers is interested in resolving my issue.

Indicate your interest in the resolution of this issue by adding the 👍 reaction. Comments such as “+1” will be removed.

Issue Analytics

  • State:open
  • Created a year ago
  • Reactions:1
  • Comments:8 (6 by maintainers)

github_iconTop GitHub Comments

2reactions
Bossorcaincommented, Oct 13, 2022

Thanks for the answer!

However there should be a few modifications with the workaround:

You should require/import the DataTypes from Sequelize first, because the Sequelize object doesn’t have these types on its own, but correct me if I’m wrong.

So the modified code should look like something like this:

const model = sequelize.define(tableName, {
  key: {
    type: DataTypes.STRING,
    allowNull: false,
    unique: true, // and this should be primaryKey if you have that type of constraint I think
  },
  value: DataTypes.STRING,
  createdAt: DataTypes.DATE,
  updatedAt: DataTypes.DATE,
});

return queryInterface.upsert(
  tableName,
  {
    key: 'my_config_key',
    value: 10,
    createdAt: new Date(),
    updatedAt: new Date(),
  },
  {
    value: 10,
  },
  {
    key: 'my_config_key',
  },
  model,
);

This should work in plain JS (not tested). However if you have TS (like me), there will be some type mismatch between QueryOptionsWithModel and ModelStatic or ModelCTor - this one is deprecated. So for TS usage I don’t really see a proper workaround for this right now. 😦

0reactions
fzn0xcommented, Oct 13, 2022

Looks like that the where argument is not being used and tested here https://github.com/sequelize/sequelize/blob/main/test/integration/model/upsert.test.js, what is your suggested solutions for this issue? @ephys @WikiRik

I was thinking a solution which we can use the where argument to lookup for rows and ignores the upsertKeys logic if where is being set.

I think it’s common for people to know that we can point to data using where in the upsert concept but it seems the built upsert doesn’t use the where option which is defined as a parameter.

Edited: not related issue.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Sequelize running migration results Cannot read property 'key ...
Just had this problem myself. From what I see in the source code Sequelize assumes you always provide the type when changing the...
Read more >
QueryInterface - Sequelize
Returns a promise that will resolve to true if the table exists in the database, false otherwise. public. async upsert(tableName: string, insertValues ...
Read more >
lib/query-interface.js | Sequelize
* This method returns an array of hashes containing information about all attributes in the table. *; * ```js; * {; * name:...
Read more >
error: cannot read property 'replace' of undefined sequelize
Trying to load all routes files in routes folder using a loop, I get this error: Cannot read property 'indexOf' of undefined. the...
Read more >
Fixing Sequelize Models with Migrations - Khalil Stemmler
Inevitably, you'll need to update your models as the database requirements ... NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found