Severity: MEDIUM
Location: TransactionContext.java:807-812 (commit2ndPhase finally calls reset()) vs rollback():247-295.
On any commit2ndPhase failure the finally calls reset(), which releases locks but skips two things rollback() does: reloading records in modifiedRecordsCache, and resetting the identity of newRecords (the #4562 fix). User-held MutableDocuments created in the failed tx keep an optimistically-assigned RID pointing at a record that was never persisted; re-saving them in the retry treats them as updates of a missing record. The phase-1 failure path correctly uses rollback().
Fix: in the finally, call rollback() (or its record-restoration portion) when !committed.
Filed from an internal engine deep-audit (2026-07). Traced to source; verify against current main before fixing and add a regression test.
Severity: MEDIUM
Location:
TransactionContext.java:807-812(commit2ndPhasefinally callsreset()) vsrollback():247-295.On any
commit2ndPhasefailure thefinallycallsreset(), which releases locks but skips two thingsrollback()does: reloading records inmodifiedRecordsCache, and resetting the identity ofnewRecords(the #4562 fix). User-heldMutableDocuments created in the failed tx keep an optimistically-assigned RID pointing at a record that was never persisted; re-saving them in the retry treats them as updates of a missing record. The phase-1 failure path correctly usesrollback().Fix: in the
finally, callrollback()(or its record-restoration portion) when!committed.Filed from an internal engine deep-audit (2026-07). Traced to source; verify against current
mainbefore fixing and add a regression test.