Open
Description
New Issue Checklist
- I am not disclosing a vulnerability.I am not just asking a question.I have searched through existing issues.I can reproduce the issue with the latest version of Parse Server.
Issue Description
Setting a subdocument entirely, followed by an unset
of a nested field causes an internal server error while the object is being saved, if the object existed beforehand.
Steps to reproduce
const myObj = new Parse.Object('MyClass');
await myObj.save(null, {useMasterKey: true});
myObj.set('data', {a: 5});
myObj.unset('data.a');
await myObj.save(null, {useMasterKey: true});
console.log('a');
Actual Outcome
error: Uncaught internal server error. Updating the path 'data.a' would create a conflict at 'data' {"code":40,"codeName":"ConflictingUpdateOperators","ok":0,"stack":"MongoServerError: Updating the path 'data.a' would create a conflict at 'data'\n at Connection.onMessage (/home/kartal/Desktop/ocell/parse-server-example/node_modules/parse-server/node_modules/mongodb/lib/cmap/connection.js:202:30)\n at MessageStream.<anonymous> (/home/kartal/Desktop/ocell/parse-server-example/node_modules/parse-server/node_modules/mongodb/lib/cmap/connection.js:62:60)\n at MessageStream.emit (events.js:400:28)\n at processIncomingData (/home/kartal/Desktop/ocell/parse-server-example/node_modules/parse-server/node_modules/mongodb/lib/cmap/message_stream.js:108:16)\n at MessageStream._write (/home/kartal/Desktop/ocell/parse-server-example/node_modules/parse-server/node_modules/mongodb/lib/cmap/message_stream.js:28:9)\n at writeOrBuffer (internal/streams/writable.js:358:12)\n at MessageStream.Writable.write (internal/streams/writable.js:303:10)\n at Socket.ondata (internal/streams/readable.js:731:22)\n at Socket.emit (events.js:400:28)\n at addChunk (internal/streams/readable.js:293:12)"}
MongoServerError: Updating the path 'data.a' would create a conflict at 'data'
at Connection.onMessage (/home/kartal/Desktop/ocell/parse-server-example/node_modules/parse-server/node_modules/mongodb/lib/cmap/connection.js:202:30)
at MessageStream.<anonymous> (/home/kartal/Desktop/ocell/parse-server-example/node_modules/parse-server/node_modules/mongodb/lib/cmap/connection.js:62:60)
at MessageStream.emit (events.js:400:28)
at processIncomingData (/home/kartal/Desktop/ocell/parse-server-example/node_modules/parse-server/node_modules/mongodb/lib/cmap/message_stream.js:108:16)
at MessageStream._write (/home/kartal/Desktop/ocell/parse-server-example/node_modules/parse-server/node_modules/mongodb/lib/cmap/message_stream.js:28:9)
at writeOrBuffer (internal/streams/writable.js:358:12)
at MessageStream.Writable.write (internal/streams/writable.js:303:10)
at Socket.ondata (internal/streams/readable.js:731:22)
at Socket.emit (events.js:400:28)
at addChunk (internal/streams/readable.js:293:12)
Expected Outcome
The object should be saved to the database with data = {}
Environment
Server
- Parse Server version:
5.3.0
- Operating system:
ubuntu 20.04
- Local or remote host (AWS, Azure, Google Cloud, Heroku, Digital Ocean, etc):
local
Database
- System (MongoDB or Postgres):
MongoDB
- Database version:
5.0.13
- Local or remote host (MongoDB Atlas, mLab, AWS, Azure, Google Cloud, etc):
local
Client
- SDK (iOS, Android, JavaScript, PHP, Unity, etc):
parse dashboard
- SDK version:
4.1.4
Activity
parse-github-assistant commentedon Nov 2, 2022
Thanks for opening this issue!
mtrezza commentedon Nov 2, 2022
Nice find! Do you want to open a PR? This may well be a Parse JS SDK issue rather than a Parse Server issue, if the SDK doesn't handle this set / unset properly. Did you look at what the SDK sends to the server?
mstniy commentedon Nov 9, 2022
I have verified that the SDK sends a malformed request to the server, so this is an SDK issue.
mtrezza commentedon Nov 9, 2022
Great, would you want to open a PR with a failing test?
mtrezza commentedon Mar 1, 2023
@mstniy Do you have any more infos on this issue? Otherwise I'll transfer it to the Parse JS SDK.
mstniy commentedon Mar 1, 2023
I am afraid not, @mtrezza . Feel free to transfer the issue. We ended up working around it.
parse-github-assistant commentedon Mar 1, 2023
Thanks for opening this issue!
mortenmo commentedon Apr 18, 2024
Looking at this for a moment, not sure there isn't more related issues.
Trying to just add
data.b
(not unsetting) and trying to get it after removes locally the previous value. It doesn't merge the ops locally.I didn't realize dot notation was even supported on set/get, but there seem to be a lot of issues with it.
Parse.Object
causes server error #2117harshbhar0629 commentedon Oct 8, 2024
Steps to reproduce
const myObj = new Parse.Object('MyClass');
await myObj.save(null, {useMasterKey: true});
myObj.set('data', {a: 5});
myObj.unset('data.a');
await myObj.save(null, {useMasterKey: true});
console.log('a');
Above code gives internal server error because of conflict.
MY Solution:
The error you're encountering is due to conflicting update operations in MongoDB. Specifically, you're trying to unset a nested field (data.a) after modifying the object, which is causing MongoDB to throw the ConflictingUpdateOperators error because it doesn't allow multiple operations that affect the same path in a single update.
Here's how you can resolve it:
Solution 1: Use Separate Saves
Instead of updating and unsetting in the same save operation, separate them into distinct saves to avoid conflicting update operators.
Explanation
Initial Save: The object is first saved with no changes.
Set and Save: The object’s data field is set with the value { a: 5 } and saved.
Unset and Save: The nested field data.a is then unset and saved again in a separate operation.
@mtrezza Please review it once:)
mtrezza commentedon Oct 8, 2024
@harshbhar0629 Good analysis, I think we may have 2 issues here:
ConflictingUpdateOperators
, then the server should not have an internal error, but the error should be caught, logged with details, and a general Parse Error should be returned, without any specific internal error details for security reasons.Would you want to write a fix? You could start with a PR that contains the code example you posted above to demonstrate the issue.
3 remaining items