Download

Updating the path would create a conflict at

One update document changes the same field twice, or a field and one of its parents: $set and $setOnInsert on the same field, $push and $pull on one array, $set on an object and on a path inside it. Give each field one operator, or split the work.

MongoDB error 40· Tested on MongoDB 8.0.32 (mongosh 2.12.0); Mongoose 8.23.0· Updated 11 October 2026

Updating the path 'qty' would create a conflict at 'qty'

What it means

An update document can use several operators ($set, $inc, $push, $setOnInsert…), but each field may be changed by only one of them, and a field and a path inside it can’t both be changed. Otherwise the result would depend on which operator ran first, so MongoDB refuses the whole update with code 40, ConflictingUpdateOperators. Nothing is written.

The message names both paths: Updating the path 'dims.h' would create a conflict at 'dims' means one operator changes dims.h while another changes dims itself.

Common causes

  1. An upsert with the same field in $set and $setOnInsert, usually to give a default on insert: $set: { qty: 1 }, $setOnInsert: { qty: 0 }.
  2. Two operators on one array: $push and $pull (or $addToSet and $pull) on the same field.
  3. A parent and a child: $set: { meta: {} } with $unset: { "meta.seen": "" }, or $set: { dims: { w: 1 }, "dims.h": 2 }.
  4. The same field twice through different operators: $set and $inc on qty.
  5. An array element and the array: $set: { "items.0": "z" } with $push: { items: "y" }.

How to fix it

Put each field in one operator

For an upsert, a field in $set is also written on insert, so it doesn’t need $setOnInsert. Keep in $setOnInsert only the fields that must not change on later updates:

db.carts.updateOne(
  { _id: 2 },
  { $set: { qty: 1 }, $setOnInsert: { createdAt: new Date() } },
  { upsert: true }
)

Use a pipeline update for “keep it, or default it”

When the new value depends on the current one (increment, but start from 0 on insert), an update pipeline can read the field and decide. It runs in one step:

db.carts.updateOne(
  { _id: 3 },
  [{ $set: {
    qty: { $add: [{ $ifNull: ["$qty", 0] }, 1] },
    createdAt: { $ifNull: ["$createdAt", "$$NOW"] }
  } }],
  { upsert: true }
)

Split operations on the same array

Run them as separate updates. bulkWrite sends them together and applies them in order:

db.carts.bulkWrite([
  { updateOne: { filter: { _id: 1 }, update: { $pull: { items: "a" } } } },
  { updateOne: { filter: { _id: 1 }, update: { $push: { items: "c" } } } }
])

Each update is atomic on its own; the pair isn’t, so another write can land between them. If that matters, use a pipeline update ($filter and $concatArrays on the array) or a transaction.

Set the parent or the children, not both

Either replace the whole object ($set: { dims: { w: 1, h: 2 } }) or set each path ($set: { "dims.w": 1, "dims.h": 2 }).

In Mongoose, check what it sends

Mongoose adds operators of its own: with upsert, it puts schema defaults in $setOnInsert (setDefaultsOnInsert), and with timestamps it sets updatedAt and createdAt. Turn on mongoose.set("debug", true) to see the final update, and look for a field in two operators.

Reproduce it

MongoDB 8.0.32, mongosh 2.12.0, in a scratch database. An upsert that matches nothing:

db.items.updateOne(
  { sku: "B-2" },
  { $set: { qty: 1 }, $setOnInsert: { qty: 0 } },
  { upsert: true }
)
MongoServerError: Updating the path 'qty' would create a conflict at 'qty'

The error’s code was 40. On a cart { _id: 1, items: ["a", "b"], meta: { seen: 1 } }, the other forms:

MongoServerError: Updating the path 'items' would create a conflict at 'items'
MongoServerError: Updating the path 'meta.seen' would create a conflict at 'meta'
MongoServerError: Updating the path 'dims.h' would create a conflict at 'dims'

The first came from $push and $pull on items (and also from $set on items.0 with $push), the second from $set: { meta: {} } with $unset of meta.seen, the third from $set: { dims: { w: 1 }, "dims.h": 2 }. $set and $inc on qty named qty.

The fixes above all worked: the upsert with qty only in $set inserted { _id: 2, createdAt: …, qty: 1 }; the pipeline upsert inserted qty: 1 and, run again, made it 2 and kept createdAt; the bulkWrite left items: ["b", "c"].

With Mongoose 8.23.0 and mongoose.set("debug", …), an upsert sent the schema’s defaults in $setOnInsert ({ plan: "free", "settings.theme": "light" }) beside our $set; it succeeded here because the fields didn’t overlap.

In Inlet

Inlet’s document editor updates only the fields you edited. Queries use mongosh syntax, so you can run the corrected updateOne, with upsert: true or a pipeline, and check the document in the inspector afterwards.

Inlet: a database client for the Mac

One native app for PostgreSQL, MySQL, SQL Server, SQLite, MongoDB and Redis. It explains errors where they happen, holds your edits until you save them, and keeps production read-only until you say so.

Version 0.1.0 · macOS 26 Tahoe or later · Apple silicon and Intel