loopback-datasource-juggler icon indicating copy to clipboard operation
loopback-datasource-juggler copied to clipboard

Model errors when using relations with the MongoDB connector cause crashes

Open zackbloom opened this issue 10 years ago • 11 comments

I have relations setup with a model which includes a property similar to this:

versions: [
  {
    id:         String
  }
]

If the versions property is actually an object, rather than an array (due to an error in saving), loopback crashes when it attempts to resolve relations involving this model.

This is the error I get:

/Users/zackbloom/s/API/node_modules/mongodb/lib/mongodb/connection/base.js:245
        throw message;
              ^
Error: Items must be an array: [object Object]
  at new List (/Users/zackbloom/s/API/node_modules/loopback-datasource-juggler/lib/list.js:25:11)
  at /Users/zackbloom/s/API/node_modules/loopback-datasource-juggler/lib/model.js:178:39
  at Array.forEach (native)
  at Function.ModelClass.forEachProperty (/Users/zackbloom/s/API/node_modules/loopback-datasource-juggler/lib/model-builder.js:271:51)
  at ModelConstructor.ModelBaseClass._initProperties (/Users/zackbloom/s/API/node_modules/loopback-datasource-juggler/lib/model.js:164:8)
  at /Users/zackbloom/s/API/node_modules/loopback-datasource-juggler/lib/dao.js:557:13
  at Array.forEach (native)
  at /Users/zackbloom/s/API/node_modules/loopback-datasource-juggler/lib/dao.js:554:12
  at /Users/zackbloom/s/API/node_modules/loopback-datasource-juggler/lib/include.js:59:11
  at /Users/zackbloom/s/API/node_modules/loopback-datasource-juggler/node_modules/async/lib/async.js:113:21
  at /Users/zackbloom/s/API/node_modules/loopback-datasource-juggler/node_modules/async/lib/async.js:24:16
  at /Users/zackbloom/s/API/node_modules/loopback-datasource-juggler/lib/include.js:124:9
  at /Users/zackbloom/s/API/node_modules/loopback-datasource-juggler/node_modules/async/lib/async.js:111:13
  at Array.forEach (native)
  at _each (/Users/zackbloom/s/API/node_modules/loopback-datasource-juggler/node_modules/async/lib/async.js:32:24)
  at Object.async.each (/Users/zackbloom/s/API/node_modules/loopback-datasource-juggler/node_modules/async/lib/async.js:110:9)
  at processIncludeItem (/Users/zackbloom/s/API/node_modules/loopback-datasource-juggler/lib/include.js:106:11)
  at /Users/zackbloom/s/API/node_modules/loopback-datasource-juggler/lib/include.js:57:5
  at /Users/zackbloom/s/API/node_modules/loopback-datasource-juggler/node_modules/async/lib/async.js:111:13
  at Array.forEach (native)
  at _each (/Users/zackbloom/s/API/node_modules/loopback-datasource-juggler/node_modules/async/lib/async.js:32:24)
  at Object.async.each (/Users/zackbloom/s/API/node_modules/loopback-datasource-juggler/node_modules/async/lib/async.js:110:9)
  at Function.Inclusion.include (/Users/zackbloom/s/API/node_modules/loopback-datasource-juggler/lib/include.js:56:9)
  at Function.f (/Users/zackbloom/s/API/node_modules/loopback-datasource-juggler/lib/jutil.js:100:15)
  at Function.f [as include] (/Users/zackbloom/s/API/node_modules/loopback-datasource-juggler/lib/jutil.js:100:15)
  at /Users/zackbloom/s/API/node_modules/loopback-connector-mongodb/lib/mongodb.js:519:33
  at /Users/zackbloom/s/API/node_modules/mongodb/lib/mongodb/cursor.js:163:16
  at commandHandler (/Users/zackbloom/s/API/node_modules/mongodb/lib/mongodb/cursor.js:709:16)
  at /Users/zackbloom/s/API/node_modules/mongodb/lib/mongodb/db.js:1846:9
  at Server.Base._callHandler (/Users/zackbloom/s/API/node_modules/mongodb/lib/mongodb/connection/base.js:445:41)
  at /Users/zackbloom/s/API/node_modules/mongodb/lib/mongodb/connection/server.js:468:18
  at [object Object].MongoReply.parseBody (/Users/zackbloom/s/API/node_modules/mongodb/lib/mongodb/responses/mongo_reply.js:68:5)
  at [object Object].<anonymous> (/Users/zackbloom/s/API/node_modules/mongodb/lib/mongodb/connection/server.js:426:20)
  at [object Object].EventEmitter.emit (events.js:95:17)
  at [object Object].<anonymous> (/Users/zackbloom/s/API/node_modules/mongodb/lib/mongodb/connection/connection_pool.js:201:13)
  at [object Object].EventEmitter.emit (events.js:98:17)
  at Socket.<anonymous> (/Users/zackbloom/s/API/node_modules/mongodb/lib/mongodb/connection/connection.js:339:18)
  at Socket.EventEmitter.emit (events.js:95:17)
  at Socket.<anonymous> (_stream_readable.js:746:14)
  at Socket.EventEmitter.emit (events.js:92:17)
  at emitReadable_ (_stream_readable.js:408:10)
  at emitReadable (_stream_readable.js:404:5)
  at readableAddChunk (_stream_readable.js:165:9)
  at Socket.Readable.push (_stream_readable.js:127:10)
  at TCP.onread (net.js:528:21)

The error itself isn't terrible, but I'd certainly rather it be returned through the HTTP request, rather than crashing the entire app.

I've tried wrapping parts of that stack in a try block, but it looks like the mongodb connector does some fancy magic with nextTick to bypass the actual stack.

zackbloom avatar May 14 '14 20:05 zackbloom

We'll have to use domain or Zone.js to deal with uncaught errors.

raymondfeng avatar Jul 23 '14 18:07 raymondfeng

How is this not critical? By using this bug you can crash the server simply by doing a REST insert (and it keeps crashing whenever the instance is accessed until you delete the row manually from the database).

nullEuro avatar Apr 24 '15 21:04 nullEuro

+1 This is a critical error. I don't even get to catch the error because the server crashes before my code execution just by using a /POST with wrong data.

ciokan avatar Aug 27 '15 14:08 ciokan

+1 I verified that a database entry that has an object { } instead of an expected array [ ] does indeed crash loopback. Malformed data in the database is not at all desirable, but it should NOT crash a loopback. Loopback should send an HTTP error message instead of crashing.

jamesobd avatar Jun 10 '16 17:06 jamesobd

Any news on the status of this bug? Seems pretty bad

bradwbradw avatar Nov 12 '16 23:11 bradwbradw

When using not only the mongoDB, even memory DB, PUT operation with simple string on array object make server CRASH! Is there any way to make server not to crash? This is a severe defect on API server.

I may change the array type in the model to hasMany relation. But, it requires many POST operations for simple strings. I have tried EmbedsMany relation. But, PUT operation on EmbedsMany property leads the same error, "Uncaught Error: could not create List from JSON string" and SERVER CRASH.

sanori avatar Dec 02 '16 02:12 sanori

I found a workaround to avoid server crash. In, for example, doc-model.js:

  docModel.observe('before save', function(ctx, next) {
    if (ctx.data && ctx.data.versions && !Array.isArray(ctx.data.versions)) {
      var err = new Error();
      err.status = 422;
      err.message = 'versions should be array type';
      return next(err);
    }
    next();
  });

This code make server not crash, but returns error. I guess that 'before save' hook runs before loopback-datasource-juggler converting data.

It would not be the part of loopback-datasource-juggler. But, it would be helpful for the people like me, so I leave this comment.

sanori avatar Dec 02 '16 08:12 sanori

why is this still open and not resolved?

skyserpent avatar Mar 06 '17 05:03 skyserpent

Would one of you guys like to submit a PR to fix or provide a sample project for us to clone/reproduce on our end?

superkhau avatar Mar 06 '17 18:03 superkhau

this still isn't fixed

Unhandled error for request POST /api/v3/Policies/updatewhere?access_token=XXX Error: could not create List from JSON string: "g"

"retrieveEmailsToBeNotified": [ "string" ],

lukegorman avatar Aug 08 '19 09:08 lukegorman

@lukegorman thank you for bringing this problem to our attention. Can you please create a small application reproducing the issue? See https://loopback.io/doc/en/contrib/Reporting-issues.html#loopback-3x-bugs

bajtos avatar Sep 27 '19 12:09 bajtos