Summary
Long-running MCP server processes cache mempalace and chromadb in sys.modules at startup and never reload. Users who upgrade mempalace or its dependencies mid-session continue serving tool calls with stale code, leading to silent data corruption or API mismatch errors. Claude Code users regularly hit this because a single Claude Code session (and its dedicated MCP server) can live for days or weeks via session resume.
Problem scenario
We experienced this during the chromadb 0.6.x → 1.5.7 transition enabled by PR #690 (which removed the <0.7 upper bound):
- Claude Code session started on day 1 with
mempalace + chromadb 0.6.x — MCP server imports both into memory
- User runs
pipx install --force -e . on day 5 (or any other upgrade path: pip install -U mempalace, uv pip install -U, etc.) — pipx venv now has chromadb 1.5.7
- The already-running MCP server is oblivious —
sys.modules['chromadb'] is still pinned to 0.6.x in memory
- User continues issuing
mempalace_add_drawer / mempalace_diary_write calls via MCP
- Those writes go through the 0.6.x code path and produce database rows with legacy format (e.g.,
seq_id as BLOB instead of INTEGER)
- A fresh process (CLI mining, or a newly-started Claude Code session) reads those rows and crashes during compaction with errors like:
chromadb.errors.InternalError: Error in compaction: Error reading from metadata segment reader:
error occurred while decoding column 0: mismatched types;
Rust type `u64` (as SQL type `INTEGER`) is not compatible with SQL type `BLOB`
or
'dict' object has no attribute 'dimensionality'
There is no warning or error at tool-call time in the stale MCP server — it reports success. The inconsistency is only discovered later, when a fresh process hits the legacy rows.
Impact
Reproducing
pipx install -e . — note the installed mempalace and chromadb versions
- Start Claude Code and make any MCP tool call (forces MCP server startup → imports)
- On the host,
pipx install --force -e . or pip install -U chromadb — upgrade in the same venv
- In the existing Claude Code session, call
mempalace_add_drawer — succeeds using stale library
- Start a new Claude Code session or run
mempalace mine from the CLI — crashes on the first write that touches metadata touched by the stale process
Suggested fixes (not mutually exclusive)
A. Version check at tool-call time (minimum viable fix)
On MCP server startup, record the running versions:
import importlib.metadata
_STARTUP_MEMPALACE_VERSION = importlib.metadata.version(\"mempalace\")
_STARTUP_CHROMADB_VERSION = importlib.metadata.version(\"chromadb\")
On each tool call, compare against the currently installed versions. If they differ, return a clear error:
{
\"error\": \"MCP server library is stale (started with mempalace X.Y.Z / chromadb A.B.C, disk has X.Y.W / chromadb A.B.D). Restart the MCP server to pick up the new version.\",
\"action_required\": \"restart_mcp_server\"
}
B. Refuse writes on mismatch
If any version mismatch is detected, disable write tools (add_drawer, diary_write, kg_add, mine via MCP, etc.) but keep read tools functional. Prevents further inconsistency while still letting the user read their palace.
C. Self-restart via os.execv()
More aggressive: on detecting staleness, os.execv(sys.executable, [sys.executable, \"-m\", \"mempalace.mcp_server\"]) to replace the current process with a fresh Python. Risk: loses any in-flight state, not always safe in Python processes with threads or C extensions (chromadb has Rust bindings).
D. Documentation-only mitigation (until a code fix lands)
Update README, plugin docs, and PR #340's description with a note about restarting MCP servers after any mempalace or chromadb upgrade. This is what Claude Code users currently need to do manually.
Related
Summary
Long-running MCP server processes cache
mempalaceandchromadbinsys.modulesat startup and never reload. Users who upgrade mempalace or its dependencies mid-session continue serving tool calls with stale code, leading to silent data corruption or API mismatch errors. Claude Code users regularly hit this because a single Claude Code session (and its dedicated MCP server) can live for days or weeks via session resume.Problem scenario
We experienced this during the
chromadb0.6.x → 1.5.7 transition enabled by PR #690 (which removed the<0.7upper bound):mempalace+chromadb 0.6.x— MCP server imports both into memorypipx install --force -e .on day 5 (or any other upgrade path:pip install -U mempalace,uv pip install -U, etc.) — pipx venv now haschromadb 1.5.7sys.modules['chromadb']is still pinned to 0.6.x in memorymempalace_add_drawer/mempalace_diary_writecalls via MCPseq_idas BLOB instead of INTEGER)There is no warning or error at tool-call time in the stale MCP server — it reports success. The inconsistency is only discovered later, when a fresh process hits the legacy rows.
Impact
mempalace migratedetects read compatibility but not write/compaction compatibility (fix: mempalace migrate produces incomplete ChromaDB 0.6.x schema #722). PR feat: post-migration schema validation for mempalace migrate #735 addresses the schema validation gap after migration, but a stale in-memory process bypasses migration entirely.Reproducing
pipx install -e .— note the installedmempalaceandchromadbversionspipx install --force -e .orpip install -U chromadb— upgrade in the same venvmempalace_add_drawer— succeeds using stale librarymempalace minefrom the CLI — crashes on the first write that touches metadata touched by the stale processSuggested fixes (not mutually exclusive)
A. Version check at tool-call time (minimum viable fix)
On MCP server startup, record the running versions:
On each tool call, compare against the currently installed versions. If they differ, return a clear error:
{ \"error\": \"MCP server library is stale (started with mempalace X.Y.Z / chromadb A.B.C, disk has X.Y.W / chromadb A.B.D). Restart the MCP server to pick up the new version.\", \"action_required\": \"restart_mcp_server\" }B. Refuse writes on mismatch
If any version mismatch is detected, disable write tools (
add_drawer,diary_write,kg_add,minevia MCP, etc.) but keep read tools functional. Prevents further inconsistency while still letting the user read their palace.C. Self-restart via
os.execv()More aggressive: on detecting staleness,
os.execv(sys.executable, [sys.executable, \"-m\", \"mempalace.mcp_server\"])to replace the current process with a fresh Python. Risk: loses any in-flight state, not always safe in Python processes with threads or C extensions (chromadb has Rust bindings).D. Documentation-only mitigation (until a code fix lands)
Update README, plugin docs, and PR #340's description with a note about restarting MCP servers after any mempalace or chromadb upgrade. This is what Claude Code users currently need to do manually.
Related
mempalace-mcpconsole entry point making the MCP server actually work for pipx/uv users. This bug was latent before fix: add mempalace-mcp entry point for pipx/uv compatibility #340 because pipx/uv users couldn't run the MCP server at all. Our fix unlocks the door.chromadb<0.7upper bound, creating the version mismatch gradient users can cross