Context
Consumer: CDP MCP / CascadeIDE intent-workspace seat DB (EF Core OutWit.Database.EntityFramework 1.0.3).
Bug
When Open fails with torn free-list / ArgumentOutOfRangeException: Page number … out of range (FreePage ≥ TotalPageCount after kill/remount pressure), the process often keeps an exclusive FileShare.None handle after the failed open/Dispose.
Subsequent opens then fail with IOException: … being used by another process within ~50ms (no real contention), and quarantine/File.Move of the torn file also fails until the process is killed.
Expected
Failed Open must not leave a sticky exclusive OS handle. Dispose/failed Open path should release the file so callers can quarantine or reopen.
Repro sketch
- Produce a large seat
*.witdb with torn free-list (dual-seat/FileShare fights or abrupt Kill mid-write historically did this).
new DbContext(...UseWitDb...).Database open / EnsureCreated → pageNumber OOR.
- Immediately retry Open or
File.Move of the same path → being used by another process while no other process holds the file.
- GC + sleep sometimes insufficient; process Kill clears the leak.
Impact
Forced us to leave WitDB for seat storage (migrating to SQLite). Filing so the engine can fix handle lifetime on failed Open.
Context
Consumer: CDP MCP / CascadeIDE intent-workspace seat DB (EF Core
OutWit.Database.EntityFramework1.0.3).Bug
When
Openfails with torn free-list /ArgumentOutOfRangeException: Page number … out of range(FreePage ≥ TotalPageCount after kill/remount pressure), the process often keeps an exclusiveFileShare.Nonehandle after the failed open/Dispose.Subsequent opens then fail with
IOException: … being used by another processwithin ~50ms (no real contention), and quarantine/File.Moveof the torn file also fails until the process is killed.Expected
Failed Open must not leave a sticky exclusive OS handle. Dispose/failed Open path should release the file so callers can quarantine or reopen.
Repro sketch
*.witdbwith torn free-list (dual-seat/FileShare fights or abrupt Kill mid-write historically did this).new DbContext(...UseWitDb...).Databaseopen / EnsureCreated →pageNumberOOR.File.Moveof the same path →being used by another processwhile no other process holds the file.Impact
Forced us to leave WitDB for seat storage (migrating to SQLite). Filing so the engine can fix handle lifetime on failed Open.