litedb-org/LiteDB · critical · LiteException

0

0

Error message

MemoryCache: removed in-use memory page. This situation has no way to fix (yet). Throwing exception to avoid database corruption. No other thread can read/write from database now.

What it means

A critical internal engine guard in MemoryCache. During page eviction, a page that was marked for removal was found to still have a non-zero ShareCounter (in-use by a reader/writer), AND re-adding it to the readable set also failed (another thread already inserted a different page at that key). To prevent silent memory corruption, the engine throws this LiteException (code 0) and considers the database unsafe for further I/O.

Source

Thrown at LiteDB/Engine/Disk/MemoryCache.cs:331

                    .Select(x => x.Key)
                    .Take(segmentSize)
                    .ToArray();

                // move pages from readable list to free list
                foreach (var key in readables)
                {
                    var removed = _readable.TryRemove(key, out var page);

                    ENSURE(removed, "page should be in readable list before moving to free list");

                    // if removed page was changed between make array and now, must add back to readable list
                    if (page.ShareCounter > 0)
                    {
                        // but wait: between last "remove" and now, another thread can added this page
                        if (!_readable.TryAdd(key, page))
                        {
                            // this is a terrible situation, to avoid memory corruption I will throw expcetion for now
                            throw new LiteException(0, "MemoryCache: removed in-use memory page. This situation has no way to fix (yet). Throwing exception to avoid database corruption. No other thread can read/write from database now.");
                        }
                    }
                    else
                    {
                        ENSURE(page.ShareCounter == 0, "page should not be in use by anyone");

                        // clean controls
                        page.Position = long.MaxValue;
                        page.Origin = FileOrigin.None;

                        _free.Enqueue(page);
                    }
                }

                LOG($"re-using cache pages (flushing {_free.Count} pages)", "CACHE");
            }
            else
            {

View on GitHub (pinned to f906a5f850)

Solutions

  1. Increase the memory cache / page limit via connection string pragma (e.g., increase the size budget) to reduce eviction pressure.
  2. Reduce concurrency or batch writes to lower simultaneous page contention.
  3. Report this as an engine bug with reproduction details; it indicates an unresolved race in MemoryCache.
  4. Restart the application to get a clean cache state; run a checkpoint/recovery to verify database integrity.
Defensive patterns

Strategy: try-catch

Try / catch

try { /* engine operation under high concurrency */ }
catch (LiteException ex) when (ex.Message.Contains("removed in-use memory page"))
{ /* database is unsafe; stop all I/O, restart process, verify integrity */ }

Prevention

When it happens

Trigger: High-concurrency workloads with many simultaneous readers/writers that pressure the memory cache into aggressive eviction. A race condition between page share-count updates and the eviction loop. This is an engine-level concurrency edge case, not user-logic error.

Common situations: Heavy parallel read/write load exceeding the configured cache size. Bugs or version regressions in the engine's page-sharing logic. Running on hardware/OS combinations with unusual threading scheduling. Extremely large datasets with limited RAM.

Related errors


AI-assisted analysis of litedb-org/LiteDB@f906a5f850 (2026-08-13). Data as JSON: /api/errors/4bcf5aa70b720138. Report an issue: GitHub.