Fixing MongoDB's error "'$' by itself is not a valid FieldPath"
Tags: mongodb, mongoose, node, javascript
Published: 2020-05-05 21:19:24

---
title: Fixing MongoDB's error "'$' by itself is not a valid FieldPath"
published: true
description: I had an issue with MongoDB pipeline powered updates that I couldn't find a solution to online, so I solved it myself and decided to write down my solution in case anyone comes across the same issue.
tags: mongodb, mongoose, node, javascript
---

I recently had to deal with a small issue working with **update operations and aggregation pipelines in MongoDB**. I couldn't find much help online to fix it, but I finally managed to understand it and decided to write my findings down to help anyone that may come across the same issue in the future.

# The code
I was trying to create an update operation using aggregation pipelines on a Node.js project with mongoose. My code looked something like this:

```js
// Model schema
let productSchema = new Schema({
    name: { type: String, required: true },
    description: { type: String, required: false },
    currency: { type: String, required: false },
    price: { type: Number, required: true },
    createdAt: { type: Date, default: Date.now, required: true },
    updatedAt: { type: Date, required: false },
    tags: [String],
});

// Update operation
module.exports.update = async (product) => {

    await productModel.findByIdAndUpdate(product._id,
        [{
            $set:
            {
                name: product.name,
                description: product.description,
                currency: product.currency,
                price: product.price,
                updatedAt: '$$NOW',
                tags: { $concatArrays: [ '$tags', product.newTags  ] }
            }
        }],
        { 
            runValidators: true
        });
}
```

The previous code is supposed to find a product by id and update its properties, setting the current date in the `updatedAt` property and concatenating the existent tags with some new tags.

Looks fine, right?

# The error

But when I executed the update function, the following error was thrown by MongoDB:

```json
{
    "ok": 0,
    "errmsg": "'$' by itself is not a valid FieldPath",
    "code": 16872,
    "codeName": "Location16872",
    "name": "MongoError"
}
```

So after some debugging and tests I realized where the issue was. First let me show you how the `product` object that I was receiving in the arguments looked like: 

```json
{
    "name": "Lenovo Thinkbook 13s",
    "description": "The ThinkBook 13s laptop is a lightweight and durable, business laptop with amazing entertainment features.",
    "currency": "$",
    "price": 723,
    "newTags": [ "laptop", "lenovo" ]
}
```

The issue was in the `currency` property value. The value was "$", which is a character used by MongoDB to identify [field paths](https://docs.mongodb.com/manual/meta/aggregation-quick-reference/#field-paths). So the error message was actually really clear, but it was not obvious for me at first sight.

# The solution
Luckily the solution to this issue was pretty simple, I just had to use the `$literal` operator to wrap up my `currency` new value, like this:

```js
module.exports.update = async (product) => {

    await productModel.findByIdAndUpdate(product._id,
        [{
            $set:
            {
                name: product.name,
                description: product.description,
                currency: { $literal: product.currency }, // <--- here!
                price: product.price,
                updatedAt: '$$NOW',
                tags: { $concatArrays: [ '$tags', product.newTags  ] }
            }
        }],
        { 
            runValidators: true
        });
}
```

## About `$literal`
`$literal` is an aggregation pipeline operator that receives a value and makes sure the aggregation pipeline *doesn't interpret it as a field path*, and uses its **literal** value instead.

Read more about this operator in [MongoDB's docs](https://docs.mongodb.com/manual/reference/operator/aggregation/literal/).

# Test repo
I created a github repo to test the issue and its solution:

 {% github pawap90/mongoose-literal-examples %} 


# Thoughts? 💬
Have you ever come across this issue? Was this article useful?