sequelize: findOrCreate fails concurrently when unique attribute contains comma in value. Postgres unique constraint error incorrectly parses error message 23505 when the value contains a ','.

What you are doing?

Trying to concurrently use findOrCreate when an attribute set to unique, would contain a comma.

'use strict';

const Sequelize = require('sequelize');

//first connect to the database
const database = new Sequelize('database', 'user', 'password', {
    dialect: 'postgres',
    host: '127.0.0.1',
    port: 5432,

    pool: {
        max: 5,
        min: 0,
        idle: 10000
    },
});

return database.authenticate()
.then(() => {
    //success connecting,
    console.log('database connected');
    return database;
})
.then(database => {
    const containerModel = database.define('TestContainer', {
        name: {
            type: Sequelize.DataTypes.STRING(32),
            allowNull: false,
            unique: 'name',
        },
    });

    return database.sync({
        alter: true,
        force: false,
    })
    .then(database => {
        return database.transaction({
            autoCommit: false,
        })
        .then(transaction => {
            return Promise.all(['hello, world', 'hello, world'].map(name => {
                console.log(`findOrCreate({name: '${name}'})`);
                return containerModel.findOrCreate({
                    where: {
                        name: name,
                    },
                    defaults: {
                        name: name,
                    },
                    transaction: transaction,
                    returning: true,
                });
            }))
            .then(() => {
                transaction.rollback();
            })
            .catch(() => {
                transaction.rollback();
            });
        });
    });
})
.catch(err => {
    //failed to connect
    console.error(err);
    process.exit(1);
});

What do you expect to happen?

concurrent operations to succeed without fail!

What is actually happening?

So lets say i set attribute of my Model attribute ‘name’ to unique. If i were to try and findOrCreate multiple of these models concurrently, and there is a unique validation error, then it fails!

It fails because the findOrCreate checks the fields in the err object generated by postgres/query.js. The parsing of said fields is done from the error message generated by postgres. In the postgres/query.js it is splitting the regex matched values by ‘,’ for both the field name and value. This incorrectly truncates the field value if it contained a ‘,’. When the findOrCreate attempts to check for concurrency, it fails because the reported value from the error and the value its expecting do not match!

Get an error of

TestContainer#findOrCreate: value used for name was not equal for both the find and the create calls, ‘hello, world’ vs ‘hello’

Dialect: postgres Database version: 9.6 Sequelize version: master

About this issue

  • Original URL
  • State: open
  • Created 7 years ago
  • Reactions: 5
  • Comments: 17 (6 by maintainers)

Most upvoted comments

Experiencing the same issue with PG 10.3. In addition to that, I have a similar issue with PostGIS fields (geography(Point,4326)) and findOrCreate

Error: city#findOrCreate: value used for coordinates was not equal for both the find and the create calls, ‘[object Object]’ vs ‘0101000020E61000007767EDB60B1D2140E36BCF2C09144940’

Here is a list of all coordinates that fail with the above error:

‘0101000020E61000001E1B81785DCF2940A835CD3B4E694940’ ‘0101000020E610000013D6C6D809572A40069FE6E4453E4A40’ ‘0101000020E61000000C59DDEA39592B4006BB61DBA2284A40’ ‘0101000020E6100000F38E537424EF2340C6A70018CFC64A40’ ‘0101000020E6100000ED647094BC7A2240B97020240B0C4940’ ‘0101000020E61000002EE23B31EBF52140C32ADEC83C2E4840’ ‘0101000020E6100000CA54C1A8A47E294073F4F8BD4D1F4840’ ‘0101000020E61000006902452C626833409DF4BEF1B51D4B40’ ‘0101000020E6100000594C6C3EAE4D2B40349D9D0C8E424A40’ ‘0101000020E6100000834C327216D61C40780B24287EC44940’ ‘0101000020E61000007767EDB60B1D2140E36BCF2C09144940’ ‘0101000020E6100000C53D963E74312C40F9A067B3EA834940’ ‘0101000020E6100000626534F2792D2D40F566D47C955E4940’

Having the same issue with Postgres. I created a Model that contains only id (unique, int, auto-increment) and message (text). Here are my findings:

  • Despite receiving an error, the row is actually created with the correct message on the first time;
  • The error happens only when the message doesn’t exist;
  • Subsequent calls with the same message work with no issues.

This issue is also occurring for MySQL, with / present for in the value for an attribute with unique constraint. In my case, it seems to be doing something different.

For example if I were to pass following values to findOrCreate:

where: {
    uniqueStringParameter: '12345/1234567/text/123',
    uniqueIntegerParameter: 789
  },
  defaults: { jsonData: {} }

I would get the error:

Error: ModelName#findOrCreate: value used for uniqueStringParameter was not equal for both the find and the create calls, ‘12345/1234567/text/123’ vs ‘789’

(Note that it is comparing the values passed for uniqueStringParameter and uniqueIntegerParameter)

This is also difficult to reproduce since it only happens when findOrCreate runs concurrently.

Should I open a new issue for this?

still a problem fwiw

@idris Can you please convert that to a complete MVCE that I can copy-paste and run? Thanks!

By the way, this same issue happens with ) in the string as well as ,