$set l'opérateur est utilisé sur upsert aussi. Il est donc absurde de faire référence aux mêmes champs sur $set et $setOnInsert .
Essayez ceci sur une collection vide :
db.items.remove();
db.items.update({},{$set:{a:1},$setOnInsert:{b:2}},{upsert:1})
db.items.find({});