Fixing MongoDB's error "'$' by itself is not a valid FieldPath"
Paula Santamaría
Posted on May 5, 2020
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:
// Model schemaletproductSchema=newSchema({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 operationmodule.exports.update=async (product)=>{awaitproductModel.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:
{"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:
{"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. 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:
$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.