Strapi: Delete item of my model but returns me an error

Created on 29 Jun 2018  路  39Comments  路  Source: strapi/strapi




Informations

  • Node.js version:9.7.0
  • npm version: 5.6.0
  • Strapi version: 3.0.0-alpha.12.6
  • Database: mongodb 3.6
  • Operating system: Windows 64bits

What is the current behavior?

deleted an item of my application, but me returned this error
MongoError: '$pull' is empty. You must specify a field like so: {$pull: {: ...}}

Steps to reproduce the problem
Create an model called "combo", have n->n relation of model called auxservice, and try to deleted that

What is the expected behavior?
dont return any errors just my response

Suggested solutions

high confirmed bug

Most helpful comment

Same here, version 3.0.0-alpha.24

All 39 comments

Hello @Nyeedz

I'm not able to reproduce. Can you give me precise steps to reproduce.

Did you migrate your app or it's a fresh new app ?

Hi, I followed the steps for the app migration on the github strapi page, but give me the same error, i tried to create another application, with the strapi new command, and copy my models off my api folder, and my realations and fields of my user.settings.json and still get the same error, deleted my item of my model but i get this error when i send the DELETE request to my http://localhost:1337/model/:id

Can you give me your models please to be able to reproduce your issue.

Did you make custom update of services or controllers ?

I dont make any custom controllers or services, just create an model in strapi interface

my model:

{
  "connection": "default",
  "collectionName": "combo",
  "info": {
    "name": "combo",
    "description": ""
  },
  "options": {
    "timestamps": true
  },
  "attributes": {
    "title": {
      "type": "string"
    },
    "price": {
      "type": "float"
    },
    "auxServices": {
      "collection": "auxservice",
      "via": "combo"
    },
    "gifts": {
      "collection": "gift",
      "via": "combo"
    },
    "order": {
      "model": "order",
      "via": "combos"
    },
    "description": {
      "type": "string"
    },
    "visible": {
      "type": "boolean"
    },
    "users": {
      "collection": "user",
      "dominant": true,
      "via": "combos",
      "plugin": "users-permissions"
    },
    "picture": {
      "type": "text"
    }
  }
}

my controller

'use strict';

/**
 * Combo.js controller
 *
 * @description: A set of functions called "actions" for managing `Combo`.
 */

module.exports = {

  /**
   * Retrieve combo records.
   *
   * @return {Object|Array}
   */

  find: async (ctx) => {
    return strapi.services.combo.fetchAll(ctx.query);
  },

  /**
   * Retrieve a combo record.
   *
   * @return {Object}
   */

  findOne: async (ctx) => {
    if (!ctx.params._id.match(/^[0-9a-fA-F]{24}$/)) {
      return ctx.notFound();
    }

    return strapi.services.combo.fetch(ctx.params);
  },

  /**
   * Count combo records.
   *
   * @return {Number}
   */

  count: async (ctx) => {
    return strapi.services.combo.count(ctx.query);
  },

  /**
   * Create a/an combo record.
   *
   * @return {Object}
   */

  create: async (ctx) => {
    return strapi.services.combo.add(ctx.request.body);
  },

  /**
   * Update a/an combo record.
   *
   * @return {Object}
   */

  update: async (ctx, next) => {
    return strapi.services.combo.edit(ctx.params, ctx.request.body) ;
  },

  /**
   * Destroy a/an combo record.
   *
   * @return {Object}
   */

  destroy: async (ctx, next) => {
    return strapi.services.combo.remove(ctx.params);
  }
};

returns me this error when i try to send an DELETE request

response of server

{
    "message": "An internal server error occurred",
    "statusCode": 500,
    "error": "Internal Server Error"
}

console error:

{ MongoError: '$pull' is empty. You must specify a field like so: {$pull: {<field>: ...}}
    at Function.MongoError.create (C:\Desenvolvimento\Za9\salo-api\node_modules\mongodb-core\lib\error.js:45:10)
    at toError (C:\Desenvolvimento\Za9\salo-api\node_modules\mongodb\lib\utils.js:149:22)
    at C:\Desenvolvimento\Za9\salo-api\node_modules\mongodb\lib\collection.js:1029:39
    at C:\Desenvolvimento\Za9\salo-api\node_modules\mongodb-core\lib\connection\pool.js:544:18
    at process._tickCallback (internal/process/next_tick.js:112:11)
  name: 'MongoError',
  message: '\'$pull\' is empty. You must specify a field like so: {$pull: {<field>: ...}}',
  driver: true,
  index: 0,
  code: 9,
  errmsg: '\'$pull\' is empty. You must specify a field like so: {$pull: {<field>: ...}}' }

it is the pattern of strapi for model and controllers

i can zip my project for you if you want so

If you create a fresh new app (with alpha.12.6 versio) and you reproduce your models with the content type builder, does it work ?

Yes please zip your project it will be easier to test

yep this works, i created a new project with the latest version of strapi, and i reproduce my models from the start.

thx

Something in the migration look having failed :/

I'm running [email protected], but I am seeing this same error. I thought it happens only if I use the middleware functions for before/afterDestroy, but just tried with and without and there is no difference. Tried recreating my entire db, but it made no difference.

I am creating owned (by the created instance) entries in different collections on beforeCreate. Then I need to clean up those same entries (cascading delete) when a document of this type is deleted.

The following manages to delete everything that it needs to, but it still throws the error in question:

  afterDestroy: async (model, result) => {
    strapi.log.info (`Deleted Itemtype with _id: ${result._id}. Cleaning up owned data...`);

    strapi.log.info (`-->Deleting field1 with _id: ${result.field1._id}`);
    await Subtype.deleteOne ({ _id: result.field1._id });

    strapi.log.info (`-->Deleting field2 with _id: ${result.field2._id}`);
    await Subtype2.deleteOne ({ _id: result.field2._id });
  }

The end result is that everything is successfully removed from the DB, but the client's request returns an error.

I will try to make a reproducible example and will get back to you.

OK, I created a repo specifically to be able to report issues AND give you a reproducible example. Each branch there will be a different issues with all commits as atomic steps in setting up the environment for the issue to occur (from install to error). And in the README.md I have explained in detail how to reproduce the error with the last commit in the repo: https://github.com/nicroto/strapi-issues/tree/delete-issue

after a couple hours i'm getting the same error
MongoError: '$pull' is empty. You must specify a field like so: {$pull: {: ...}}

like @nicroto said, delete from database but the response returns an that error

I will check this issue this week end.

@lauriejim Thanks.

@lauriejim Thx man

Some delay sorry for that, lot of work.

@lauriejim have you made any progress on this? Does my example reproduce the problem for you?

Same error here. The Promise.all at the end of remove (api//services/.js) never resolves.

Nop I havn't time to work on. Will appreciate an investigation by the community.
Small team for a large active community.

Can you try with last version of Strapi (3.0.0-alpha.14.1.1) please.

After having migrated to 3.0.0-alpha.14.1.1, the error seems to persist.

With a fresh new project ? and fresh new database.

I've created a fresh project using 3.0.0-alpha.14.1.1 2 days ago and get error 500 Internal server error each time I try to delete an entry... But the entry is correctly removed

Hi guys, after a lot of tests, I've noticed something with this issue. The error seems to only be thrown when we try to delete a Content Type which has a many-to-many relation...
Another thing, I had encountered this issue for the first time on Debian 9, with MongoDB shell version v4.0.2. Then I tried to downgrade MongoDB to 3.4 and 3.6 and get the same error.
So, I tried to retrieve my Strapi project on my local machine, a MacBook Pro under High Sierra. I ran npm i in order to instal dependencies and then run npm run start to lunch Strapi server for test. I've created 4-5 entries to try deleting them through Postman, and... NO ERROR, the removal has been done successfully.

I thought the Strapi (or MongoDB, or node, or something else) installation was corrupt on my Debian server.
So I tried to re-install my Debian to a Ubuntu Server 16.04 and then run the script given at bottom of this article to automatically install all stuff needed. Everything was installed successfully, I could create a new Strapi project and recreate all my Content Type, create 4-5 test enties in a Content Type which gets a many-to-many relation. But in this case, the removal causes $pull error again....

Here is my local environment (Macos High Sierra) :
MongoDB shell version v4.0.2
git version: fc1573ba18aee42f97a3bb13b67af7d837826b47
allocator: system
modules: none
build environment:
distarch: x86_64
target_arch: x86_64

Here is my server environment (Ubuntu 16.04) :
MongoDB shell version v3.4.17
git version: 7c14a47868643bb691a507a92fe25541f998eca4
OpenSSL version: OpenSSL 1.0.2g 1 Mar 2016
allocator: tcmalloc
modules: none
build environment:
distmod: ubuntu1604
distarch: x86_64
target_arch: x86_64

EDIT :
I've upgraded MongoDB on my Ubuntu Server 16.04 to v3.6.8 and retried to delete entries : I still got the $pull error...
Then I've upgraded MongoDB to 4.0.2 and the error still be there...

I'm out of ideas on how could I resolve the issue and on why is this issue...

I can confirm this error using the following system environment:

Node v10.11.0

NPM 6.4.1

Strapi 3.0.0-alpha.14.1.1

MongoDB shell version v3.6.3
git version: 9586e557d54ef70f9ca4b43c26892cd55257e1a5
OpenSSL version: OpenSSL 1.1.0g  2 Nov 2017
allocator: tcmalloc
modules: none
build environment:
    distarch: x86_64
    target_arch: x86_64

No LSB modules are available.
Distributor ID:    Ubuntu
Description:    Ubuntu 18.04.1 LTS
Release:    18.04
Codename:    bionic

Error Message:

0|strapi-mongo  | { MongoError: '$pull' is empty. You must specify a field like so: {$pull: {<field>: ...}}
0|strapi-mongo  |     at Function.create (/root/test-mongo/node_modules/mongodb-core/lib/error.js:43:12)
0|strapi-mongo  |     at toError (/root/test-mongo/node_modules/mongodb/lib/utils.js:149:22)
0|strapi-mongo  |     at coll.s.topology.update (/root/test-mongo/node_modules/mongodb/lib/operations/collection_ops.js:1370:39)
0|strapi-mongo  |     at /root/test-mongo/node_modules/mongodb-core/lib/connection/pool.js:532:18
0|strapi-mongo  |     at process._tickCallback (internal/process/next_tick.js:61:11)
0|strapi-mongo  |   driver: true,
0|strapi-mongo  |   name: 'MongoError',
0|strapi-mongo  |   index: 0,
0|strapi-mongo  |   code: 9,
0|strapi-mongo  |   errmsg:
0|strapi-mongo  |    '\'$pull\' is empty. You must specify a field like so: {$pull: {<field>: ...}}',
0|strapi-mongo  |   [Symbol(mongoErrorContextSymbol)]: {} }
0|strapi-mongo  | [2018-09-24T11:46:29.551Z] debug DELETE /test2/5ba8cdb96a68b005af65ab4b (22 ms)

This error is isolated to Mongo only, does not affect MySQL/Postgres so likely and issue with mongoose.

^^^ The above was done on testing between two models joined with a manyToMany relationship. Attempting to delete would delete the object but would throw that error in the console and feed back a 500 error to the client.

Tested using Postman.

I have same error... Please check the log for investigate problem!

...based file: .../api/demos/services/Demos.js

  /**
   * Promise to remove a/an demos.
   *
   * @return {Promise}
   */

  remove: async params => {
    // Select field to populate.
    const populate = Demos.associations
      .filter(ast => ast.autoPopulate !== false)
      .map(ast => ast.alias)
      .join(' ');

      console.log('*****Populate:', populate);
      console.log('*****Params:', params);

    // Note: To get the full response of Mongo, use the `remove()` method
    // or add spent the parameter `{ passRawResult: true }` as second argument.
    const data = await Demos
      .findOneAndRemove(params, {})
      .populate(populate);

      console.log('*****Data:', data);

    if (!data) {
      return data;
    }

    await Promise.all(
      Demos.associations.map(async association => {
        const search = _.endsWith(association.nature, 'One') || association.nature === 'oneToMany' ? { [association.via]: data._id } : { [association.via]: { $in: [data._id] } };
        const update = _.endsWith(association.nature, 'One') || association.nature === 'oneToMany' ? { [association.via]: null } : { $pull: { [association.via]: data._id } };

          console.log('*****Association:', association);
          console.log('*****Search:', search);
          console.log('*****Update:', update);

        // Retrieve model.
        const model = association.plugin ?
          strapi.plugins[association.plugin].models[association.model || association.collection] :
          strapi.models[association.model || association.collection];

        return model.update(search, update, { multi: true });
      })
    );

    return data;
  }

...the result is:

*****Populate: 'view image occurrence'

*****Params: { _id: '5ba9c2c9fbbabe57e9e311f5' }

*****Data: { view:
   [ { users: [Array],
       _id: 5ba8f7ed3a1efe21172575b3,
       name: 'TEST',
       city: 'ROME',
       createdAt: 2018-09-24T14:42:53.313Z,
       updatedAt: 2018-09-24T15:01:20.232Z,
       __v: 0,
       demos: null,
       image: null,
       id: '5ba8f7ed3a1efe21172575b3' } ],
  _id: 5ba9c2c9fbbabe57e9e311f5,
  name: 'demoOFF',
  description: 'demoDES',
  start_date: 2018-09-01T00:00:00.000Z,
  end_date: 2018-09-30T00:00:00.000Z,
  type: 'demo',
  createdAt: 2018-09-25T05:08:25.069Z,
  updatedAt: 2018-09-25T05:08:25.199Z,
  __v: 0,
  image: [],
  occurrence: [],
  id: '5ba9c2c9fbbabe57e9e311f5' }


----------------------------------------------------------------------


*****Association: { alias: 'view',
  type: 'collection',
  collection: 'views',
  via: 'demos',
  nature: 'manyToMany',
  autoPopulate: true,
  dominant: true,
  plugin: undefined,
  filter: undefined }

*****Search: { demos: { '$in': [ 5ba9c2c9fbbabe57e9e311f5 ] } }

*****Update: { '$pull': { demos: 5ba9c2c9fbbabe57e9e311f5 } }


----------------------------------------------------------------------


*****Association: { alias: 'image',
  type: 'collection',
  collection: 'file',
  via: 'related',
  nature: 'manyToManyMorph',
  autoPopulate: true,
  dominant: true,
  plugin: 'upload',
  filter: 'field' }

*****Search: { related: { '$in': [ 5ba9c2c9fbbabe57e9e311f5 ] } }

*****Update: { '$pull': { related: 5ba9c2c9fbbabe57e9e311f5 } }


----------------------------------------------------------------------


*****Association: { alias: 'occurrence',
  type: 'collection',
  collection: 'occurrence',
  via: 'demos',
  nature: 'oneToMany',
  autoPopulate: true,
  dominant: false,
  plugin: undefined,
  filter: undefined }

*****Search: { demos: 5ba9c2c9fbbabe57e9e311f5 }

*****Update: { demos: null }

{ MongoError: '$pull' is empty. You must specify a field like so: {$pull: {<fiel>: ...}}
    at Function.MongoError.create (/home/lag/backOffice/node_modules/mongodb-cor/lib/error.js:45:10)
    at toError (/home/lag/backOffice/node_modules/mongodb/lib/utils.js:149:22)
    at /home/lag/backOffice/node_modules/mongodb/lib/collection.js:1029:39
    at /home/lag/backOffice/node_modules/mongodb-core/lib/connection/pool.js:54418
    at process._tickCallback (internal/process/next_tick.js:112:11)
  name: 'MongoError',
  message: '\'$pull\' is empty. You must specify a field like so: {$pull: {<fiel>: ...}}',
  driver: true,
  index: 0,
  code: 9,
  errmsg: '\'$pull\' is empty. You must specify a field like so: {$pull: {<field: ...}}' }

----------------------------------------------------------------------

...so I have checked that the error occur when the condition of:

        const search = _.endsWith(association.nature, 'One') || association.nature === 'oneToMany' ? { [association.via]: data._id } : { [association.via]: { $in: [data._id] } };
        const update = _.endsWith(association.nature, 'One') || association.nature === 'oneToMany' ? { [association.via]: null } : { $pull: { [association.via]: data._id } };

"search" and "update" are "true" and values will be:

search = { [association.via]: data._id }
update = { [association.via]: null }

...so return model.update(search, update, { multi: true }); will return error.

Any suggest for solve?

Hello! Thank you for these detail. I miss time to give you full detail about how work relations on Strapi.
It's a tricky part of the project. I will try to take a look soon as possible.

Any news on this?

I'm on version 3.0.0-alpha.14.5 and I'm seeing this error

Same here, version 3.0.0-alpha.14.5

Same here, version 3.0.0-alpha.16

Also experiencing this error on many-to-many relational items (alpha16)

For those who still have this error on many-to-many relationship, the issue is certainly because you try to remove the dominant model.

Explanation based on my experience

Environment :

node v10.15.0
strapi 3.0.0-alpha.21

Models used in my API :

_Stage.settings.json_

{
  "connection": "default",
  "collectionName": "stage",
  "info": {
    "name": "stage",
    "description": ""
  },
  "options": {
    "timestamps": true
  },
  "attributes": {
    "label": {
      "default": "",
      "type": "string"
    },
    "equipments": {
      "collection": "equipment",
      "via": "stages"
    }
  }
}

_Equipment.settings.json_

{
  "connection": "default",
  "collectionName": "equipment",
  "info": {
    "name": "equipment",
    "description": ""
  },
  "options": {
    "timestamps": true
  },
  "attributes": {
    "label": {
      "default": "",
      "type": "string"
    },
    "stages": {
      "collection": "stage",
      "via": "equipments",
      "dominant": true
    }
  }
}

What I was trying to do

From my client app, I was trying to remove an equipment with a HTTP request similar to this one :
DELETE /equipments/5c531907aaa8721c34e26afc

Strapi response to the above HTTP request

MongoError: '$pull' is empty. You must specify a field like so: {$pull: {: ...}}

Workarround

Since I was trying to remove an equipment, I updated my models to set equipments attribute in stage model dominant instead of stages attribute in equipment model.

But it is not a definitive solution because now, I can't remove a stage

Same here, version 3.0.0-alpha.24

Same here, version 3.0.0-alpha.24.1

but the error change

Error:
Parameter "obj" to Document() must be an object, got 5c91b2ccf846dc3504438d4a',
name: 'ObjectParameterError' }

This doesn't seem to be resolved. Any reason this issue was closed?

@wsalazar-peakactivity it was closed automatically in a PR. @lauriejim reopening for us to check again to see if it still exists in 25.2+

the error is gone on version 25.2+

Was this page helpful?
0 / 5 - 0 ratings

Related issues

MattAurich picture MattAurich  路  81Comments

mnlbox picture mnlbox  路  37Comments

cesarvarela picture cesarvarela  路  63Comments

lucaperret picture lucaperret  路  36Comments

johhansantana picture johhansantana  路  45Comments