Failed transactional batch request throws TypeError with Postgres
Issue
With Postgres, aborting the transaction of a batch request with transaction: true always fails if one of its requests fails. The transaction is rolled back, but:
- In Cloud Code (
ParseServerRESTController), the batch request rejects withTypeError: error.find is not a functioninstead of the per-request results. - The transactional session is not cleared from the
DatabaseControllerof the request.
abortTransactionalSession() in src/Adapters/Storage/Postgres/PostgresStorageAdapter.js calls transactionalSession.result.catch() without a handler, so it rejects with the BatchError of the rolled-back transaction. DatabaseController.abortTransactionalSession() then doesn't clear _transactionalSession, and the .catch of the batch in src/ParseServerRESTController.js calls error.find(...) on the BatchError.
Before GHSA-jhh9-hrgh-c9gv was fixed in 9.10.2-alpha.5, this contributed to that vulnerability. Since the fix, it only affects the request that sent the batch.
Reproduced on alpha (c3b46940) with a batch request with transaction: true that contains a valid create and a create with a wrong field type:
| Postgres | MongoDB (replica set) | |
|---|---|---|
Cloud Code (ParseServerRESTController) |
Rejects with TypeError: error.find is not a function |
Rejects with the per-request results |
| Transactional session cleared | No | Yes |
| Objects rolled back | Yes | Yes |
REST /batch |
HTTP 500 Internal server error. |
HTTP 500 Internal server error. |
Notes for the fix:
- REST
/batchreturns a generic HTTP 500 with both databases. With MongoDB,src/batch.jsrejects with{ response: results }, whichhandleParseErrorsturns into an internal server error; with Postgres, theBatchErrorof the abort does the same. It still needs to be clarified whether a failing transactional batch should return the per-request results instead, and whether that belongs to this fix. - The spec
should not save anything when one operation fails in a transactioninspec/ParseServerRESTController.spec.jsaccepts any error, so it doesn't detect theTypeError. - The transaction specs currently only run with Postgres in CI, see #10712.
Source: parse-community/parse-server