Found during a code-review pass (2026-07-23).
src/db/activities.rs drives transactions with raw conn.execute("BEGIN TRANSACTION") / "COMMIT TRANSACTION" (import_many, import_collection). Every inner op uses ?, so if any insert or the periodic commit fails mid-loop, the function returns early with a transaction still open on the shared &Connection. The next DB op then runs inside the abandoned transaction, or a later BEGIN fails with "cannot start a transaction within a transaction." There is no rollback path. (The author's own // todo: use conn.transaction()? comments flag this.)
Suggested fix
Use rusqlite's RAII conn.transaction() (needs &mut Connection) or unchecked_transaction(), which auto-rolls-back on drop. For periodic-commit batching, commit and begin a fresh transaction explicitly while relying on the guard for early-return rollback. This requires changing the batch paths from &Connection to &mut Connection.
Severity: medium-high (can corrupt/abort subsequent DB work after a mid-import failure).
Found during a code-review pass (2026-07-23).
src/db/activities.rsdrives transactions with rawconn.execute("BEGIN TRANSACTION")/"COMMIT TRANSACTION"(import_many,import_collection). Every inner op uses?, so if any insert or the periodic commit fails mid-loop, the function returns early with a transaction still open on the shared&Connection. The next DB op then runs inside the abandoned transaction, or a laterBEGINfails with "cannot start a transaction within a transaction." There is no rollback path. (The author's own// todo: use conn.transaction()?comments flag this.)Suggested fix
Use rusqlite's RAII
conn.transaction()(needs&mut Connection) orunchecked_transaction(), which auto-rolls-back on drop. For periodic-commit batching, commit and begin a fresh transaction explicitly while relying on the guard for early-return rollback. This requires changing the batch paths from&Connectionto&mut Connection.Severity: medium-high (can corrupt/abort subsequent DB work after a mid-import failure).