diff --git a/lib/model.js b/lib/model.js index 8b55c5d4..d93e4ab4 100644 --- a/lib/model.js +++ b/lib/model.js @@ -674,7 +674,11 @@ Model.nestRemoting = function(relationName, options, cb) { this[getterName](fkId, function(err, inst) { if (err && cb) return cb(err); if (inst instanceof relation.modelTo) { - nestedFn.apply(inst, args); + try { + nestedFn.apply(inst, args); + } catch (err) { + if (cb) return cb(err); + } } else if (cb) { cb(err, null); } @@ -688,7 +692,11 @@ Model.nestRemoting = function(relationName, options, cb) { this[getterName](function(err, inst) { if (err && cb) return cb(err); if (inst instanceof relation.modelTo) { - nestedFn.apply(inst, args); + try { + nestedFn.apply(inst, args); + } catch (err) { + if (cb) return cb(err); + } } else if (cb) { cb(err, null); } diff --git a/test/relations.integration.js b/test/relations.integration.js index 4ba459f2..f1aa72da 100644 --- a/test/relations.integration.js +++ b/test/relations.integration.js @@ -1168,6 +1168,13 @@ describe('relations - integration', function() { Page.hasMany(Note); Image.belongsTo(Book); + // fake a remote method that match the filter in Model.nestRemoting() + Page.prototype['__throw__errors'] = function() { + throw new Error('This should not crash the app'); + }; + + Page.remoteMethod('__throw__errors', { isStatic: false, http: { path: '/throws', verb: 'get' } }); + Book.nestRemoting('pages'); Image.nestRemoting('book'); @@ -1305,6 +1312,19 @@ describe('relations - integration', function() { }); }); }); + + it('should catch error if nested function throws', function(done) { + var test = this; + this.get('/api/books/' + test.book.id + '/pages/' + this.page.id + '/throws') + .end(function(err, res) { + expect(res.body).to.be.an('object'); + expect(res.body.error).to.be.an('object'); + expect(res.body.error.name).to.equal('Error'); + expect(res.body.error.status).to.equal(500); + expect(res.body.error.message).to.equal('This should not crash the app'); + done(); + }); + }); }); });