What is the form of your _id values? Are you generating those? If your code allows for two threads to simultaneously perform an upsert using the same target _id value, there’s always a chance they both result in a create attempt using that same _id value and only one succeeds.

Your two options would appear to be to either - as you say - handle the error within your application, or to ensure threads cannot use the same value of _id, perhaps by implementing a sequence using findOneAndUpdate similar to the approach described here: