Skip to content

TransactionScope._conn null reference in savepoint Dispose path is silently swallowed by catch #1741

Description

@Widthdom

Summary

DbWriter.TransactionScope has a savepoint constructor (line 71) that assigns _conn. Commit() (line 83) and Dispose() (line 111) execute RELEASE/ROLLBACK SAVEPOINT via _conn! — the null-forgiving operator suggests the author knows nullability is in play but trusts the constructor. The catch block in Dispose (line 113) silently swallows any exception, including a NullReferenceException if _conn is somehow not initialized. The combination — null-forgiving deref + silent catch — turns a constructor-init bug into a quiet "transaction never released" leak that's invisible from logs.

Where

  • src/CodeIndex/Database/DbWriter.cs:71-96 (TransactionScope savepoint constructor)
  • src/CodeIndex/Database/DbWriter.cs:111-125 (Dispose with silent catch)

Suggested approach

(1) Replace _conn! with explicit if (_conn is null) throw new InvalidOperationException(...) so the bug surfaces at the failure point rather than being eaten. (2) Have the Dispose catch block log the exception (to GlobalToolLog) before swallowing — silent swallow is fine for cleanup, but the log breadcrumb makes debugging possible. (3) Add a regression test that constructs a partial TransactionScope (via reflection or a test helper) with _conn = null and asserts the failure is observable. (4) Document the lifecycle invariants in the class XML doc.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions