MemPalace/mempalace · error · MineValidationError

FTS5/SQLite quick_check failed: {len(errors)} issue(s)

Error message

FTS5/SQLite quick_check failed: {len(errors)} issue(s)

What it means

Error "FTS5/SQLite quick_check failed: {len(errors)} issue(s)" thrown in MemPalace/mempalace.

Source

Thrown at mempalace/palace.py:1151

    # Defer-import: keeps the repair module graph out of mine's hot import path.
    from .repair import _close_chroma_handles, maybe_autoheal_fts5_index, sqlite_integrity_errors

    # Pass the live singleton so the writer's cached PersistentClient actually
    # gets closed and WAL flushes before the read-only sqlite3 re-open.
    # A transient ChromaBackend (the default) would only clear its own empty
    # `_clients` dict and leave _DEFAULT_BACKEND's live handle in place,
    # which on Windows keeps the sqlite file mmap'd.
    _close_chroma_handles(palace_path, backend=_DEFAULT_BACKEND)

    errors = sqlite_integrity_errors(palace_path)
    if errors:
        # progress=logger.info, not the default print: this runs inside the
        # MCP server process too (mcp_server.tool_mine -> miner.mine), where
        # stdout is the JSON-RPC transport -- a stray print() here would
        # corrupt the protocol stream and crash the connection.
        errors = maybe_autoheal_fts5_index(palace_path, errors, progress=logger.info)
    if errors:
        raise MineValidationError(palace_path, errors)


# Process-wide record of palaces this PROCESS already holds the lock for. Used
# by `mine_palace_lock` to short-circuit re-entrant acquisition from the same
# process (e.g. miner.mine() acquires the outer lock then calls
# ChromaCollection.upsert which now also tries to acquire). Without this guard
# the inner call would block on its own outer flock (Linux fcntl locks are per
# open file description, so a second open of the lock file from the same process
# is a distinct lock and self-conflicts / EWOULDBLOCKs).
#
# This MUST be process-wide, not thread-local: the MCP HTTP transport
# (ThreadingHTTPServer) acquires the long-lived writer-lease on one thread
# (`mcp_server._acquire_mcp_writer_lock`) but dispatches each write request on a
# different worker thread. A thread-local guard makes those handlers fail to see
# the process-held lease, re-acquire the flock, and self-conflict
# ("palace ... is held by PID <self>"). flock is per-process and HTTP writes are
# serialized by `_HTTP_REQUEST_LOCK`, so the process is the correct re-entrancy
# boundary.

View on GitHub (pinned to 06cb6987f0)

Solutions

  1. Run palace repair; restore from backup if quick_check keeps failing

When it happens

Trigger: Thrown at mempalace/palace.py:1151 when the library encounters an invalid state.

Common situations: SQLite FTS5 integrity check reported corruption.


AI-assisted analysis of MemPalace/mempalace@06cb6987f0 (2026-08-15). Data as JSON: /api/errors/64fc0a0287c49d51. Report an issue: GitHub.