Skip to content

[tx] Phase-2 commit failure uses reset() instead of rollback(), leaving dangling RIDs on user documents #4940

Description

@lvca

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.

Metadata

Metadata

Assignees

Labels

auditFindings from the 2026-07 engine deep auditbugconcurrencyThreading / concurrency / MVCC

Type

Fields

No fields configured for Bug.

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions