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.

The "catch" block is not catching the error with one transaction using chain promises

See original GitHub issue

What you are doing?

issue-6409.zip

I’m using Promises in one transaction.

With my following code, the error is silent and the “catch” is not executed.

var Q = require('q');
var models = require("../models");

var forms = require('./data/forms.json').forms || [];

var createField = function(field, formDB){

    return models.field.findOrCreate({
        where: {
            name: field.apiName,
        },
        defaults: {
            type: field.typeField,
            keyItem: field.keyItem,
            parentId: field.parentId
        }
    }).then(function(fieldDB){
        fieldDB = fieldDB[0] || fieldDB;
        return models.formField.findOrCreate({
            where: {
                formId: formDB.formId,
                fieldId: fieldDB.fieldId,
            },
            defaults: {
                customName: field.customName,
                isVisible: field.isVisible,
                isRequired: field.isRequired,
                position: field.position
            }
        });
    });
};
var createForm = function(form){
    return models.form.findOrCreate({
        where: {
            name: form.name
        }
    }).then(function(formDB){
        formDB = formDB[0] || formDB;
        return Q.all(form.fields.map(function(field){
            return createField(field, formDB);
        }));
    });
};

models.sequelize.sync().then(function () {

    var result = Q();
    forms.forEach(function (form) {
        result = result.then(function(){
            return createForm(form);
        });
    });

    result.then(function(){
        console.log("Success!");
    }).catch(function(err){
        console.log("Error!"); //********************** Doesn't work ***************************
        var msg = err;
    });
});

But using transactions, the “catch” is executed (Why? I don’t have any idea about that):

var Q = require('q');
var models = require("../models");

var forms = require('./data/forms.json').forms || [];

var createField = function(field, formDB, t){

    return models.field.findOrCreate({
        where: {
            name: field.apiName,
        },
        defaults: {
            type: field.typeField,
            keyItem: field.keyItem,
            parentId: field.parentId,
        },
        transaction: t
    }).then(function(fieldDB){
        fieldDB = fieldDB[0] || fieldDB;
        return models.formField.findOrCreate({
            where: {
                formId: formDB.formId,
                fieldId: fieldDB.fieldId,
            },
            defaults: {
                customName: field.customName,
                isVisible: field.isVisible,
                isRequired: field.isRequired,
                position: field.position
            },
            transaction: t
        });
    });
};

var createForm = function(form){
    return models.sequelize.transaction(function (t1){ 
        return models.form.findOrCreate({
            where: {
                name: form.name
            },
            transaction: t1
        }).then(function(formDB){
            formDB = formDB[0] || formDB;
            return models.sequelize.transaction(function (t2){
                return Q.all(form.fields.map(function(field){
                    return createField(field, formDB, t2);
                }));
            });
        });
    });
};

models.sequelize.sync().then(function () {

    var result = Q();
    forms.forEach(function (form) {
        result = result.then(function(){
            return createForm(form);
        });
    });

    result.then(function(){
        console.log("Success!");
    }).catch(function(err){
        console.log("Error!"); //******************** Works perfect! ***************************
        var msg = err;
    });
});

What do you expect to happen?

The catch should be executed with one transaction.

What is actually happening?

The “catch” is not executed and therefore the error is silent.

Output (The error when the catch is executed)

{
    "name": "SequelizeUniqueConstraintError",
    "message": "Validation error",
    "errors": [{
        "message": "custom_name must be unique",
        "type": "unique violation",
        "path": "custom_name",
        "value": "Site"
    }],
    "fields": {
        "custom_name": "Site"
    }
}

Dialect: postgres Database version: 9.5.3 Sequelize version: 3.23.6

Thanks in advance, Nicholls

Issue Analytics

  • State:closed
  • Created 7 years ago
  • Reactions:5
  • Comments:29 (19 by maintainers)

github_iconTop GitHub Comments

8reactions
overlookmotelcommented, Oct 28, 2016

@jdnichollsc I’m going to put this less politely than @janmeier

Are you bloody mad? I see you are very active on Github so I don’t know how you haven’t managed to understand this already.

Sending a massive load of stuff for people to wade through is rude. What it says is “My time is so important, I’m not going to bother putting any effort into this. Your time is worthless so you can spend an hour of it trying to figure out what’s going on in my huge example”.

I already gave you a long considered answer above working through your previous example as best I could with information you’d given. But you haven’t bothered to engage or reply to that either.

In conclusion: you need to put in some work yourself to help people help you.

Or put another way: wake up or fuck off!

2reactions
overlookmotelcommented, Sep 3, 2016

@jdnichollsc Going back to your very first example, does it output Success!?

I suspect this isn’t actually a matter of the error being “swallowed” in the early example, but is due to the code behaving differently depending on whether you run it in transactions or not.

There are many uses of findOrCreate() in your examples, and also you have some parallel execution going on (Q.all(form.fields.map(function(field){ ...). Within a transaction, the find() part of findOrCreate() can only see database changes made within its own transaction, so it may create() the same row again. But then when the transactions try to commit, you end up with two rows which both can’t be committed, creating the UniqueConstraint error.

You are passing the transaction explicitly between calls, so CLS is not being used. So it should not make any difference whether you use Q or Sequelize.Promise. Feel free to use whichever you prefer.

What I’m saying is that at this point, I suspect there’s no bug in Sequelize, and it’s a problem with your code.

If you want further help here, I think you first need to try to narrow down this problem yourself. In particular, you haven’t posted the data in forms so there’s no way for anyone else reading to replicate the problem.

If I were you, I would try to reduce that data down piece by piece and find out at what point the error doesn’t not occur any more. That I think will give you the clue what’s going on.

If I’m wrong, and you do still think it’s a bug in Sequelize, please come back with a single solid example of where an error is being thrown and you think it shouldn’t be. That example should include: model definition, data being used (i.e. what is in the fields.json file), and the code - everything someone else needs to get the example running on their own computer and replicate the error. Personally, I find the screencasts hard to follow.

I hope you understand that I’m trying to help!

Read more comments on GitHub >

github_iconTop Results From Across the Web

Why catch at the end of promise chain is not ... - Stack Overflow
Looks like the issue is that isUsed is being executed immediately rather than after inBlacklist resolves, so your .then() is being given a ......
Read more >
Error handling with promises - The Modern JavaScript Tutorial
Promise chains are great at error handling. When a promise rejects, the control jumps to the closest rejection handler.
Read more >
JavaScript Promises and Errors - Peter Coles
This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not...
Read more >
Promise.prototype.catch() - JavaScript - MDN Web Docs
The catch method is used for error handling in promise composition. Since it returns a Promise , it can be chained in the...
Read more >
Practical Guide to Fp-ts P3: Task, Either, TaskEither
A Promise provides no indication about whether the function can fail. ... When you use a catch block, the error is always of...
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