Summary
Lossless-Claw can hit Error: cannot start a transaction within a transaction during restart/bootstrap pressure because multiple sessions share one SQLite DatabaseSync connection, while transaction serialization is only per session and some transaction scopes span awaited async work.
Proven / strongly supported observations
- One
LcmContextEngine instance shares a single DatabaseSync handle across stores/sessions.
withSessionQueue() serializes only by sessionKey || sessionId, not globally by DB handle.
bootstrap() wraps work in conversationStore.withTransaction(async () => { ... }).
withTransaction() issues BEGIN IMMEDIATE, then awaits the operation.
- Bootstrap performs awaited async work inside that transaction, including session-file reads.
- Under restart, multiple sessions re-bootstrap in the same runtime window.
- We observed a real runtime error:
context engine bootstrap failed: Error: cannot start a transaction within a transaction.
Why this is unsafe
If session A begins a transaction on the shared DB and then yields on async work, session B (different queue key) can still enter its own transaction path on the same DB connection. SQLite then throws:
cannot start a transaction within a transaction
This appears most likely during restart/bootstrap storms, but the design issue is broader than bootstrap alone: any cross-session DB-mutating operation using the shared connection can collide if transaction scope crosses await.
Candidate fix directions
- Do not hold SQLite transactions across async file/network/stream work.
- Move bootstrap read/parse planning outside the transaction; keep only the short write/apply section transactional.
- Add a process-global DB transaction/write mutex (not only per-session queueing).
- Add regression coverage for concurrent multi-session bootstrap / DB-mutating operations.
Reproduction shape
- shared engine / shared DB handle
- multiple sessions wake after restart
- one session enters bootstrap transaction and yields during file read
- another session enters a transaction path on the same DB
- nested transaction error is thrown
Notes
A clean v0.6.0 package appears to match the currently synced local source for the relevant bootstrap/transaction files, so this does not look like a packaging-only issue.
Summary
Lossless-Claw can hit
Error: cannot start a transaction within a transactionduring restart/bootstrap pressure because multiple sessions share one SQLiteDatabaseSyncconnection, while transaction serialization is only per session and some transaction scopes span awaited async work.Proven / strongly supported observations
LcmContextEngineinstance shares a singleDatabaseSynchandle across stores/sessions.withSessionQueue()serializes only bysessionKey || sessionId, not globally by DB handle.bootstrap()wraps work inconversationStore.withTransaction(async () => { ... }).withTransaction()issuesBEGIN IMMEDIATE, then awaits the operation.context engine bootstrap failed: Error: cannot start a transaction within a transaction.Why this is unsafe
If session A begins a transaction on the shared DB and then yields on async work, session B (different queue key) can still enter its own transaction path on the same DB connection. SQLite then throws:
cannot start a transaction within a transactionThis appears most likely during restart/bootstrap storms, but the design issue is broader than bootstrap alone: any cross-session DB-mutating operation using the shared connection can collide if transaction scope crosses
await.Candidate fix directions
Reproduction shape
Notes
A clean v0.6.0 package appears to match the currently synced local source for the relevant bootstrap/transaction files, so this does not look like a packaging-only issue.