Repository navigation
Description
Which server?
memory (@modelcontextprotocol/server-memory)
Server version
2.1.0
How did you run the server?
From a clone of this repository
Transport
stdio
Protocol era
Modern (2026-07-28)
MCP client and version
Claude Desktop / Autonomous Agent Orchestrator
Operating system and runtime
Linux / Node.js v24+
Server configuration
{
"mcpServers": {
"memory": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-memory"]
}
}
}Steps to reproduce
- Run @modelcontextprotocol/server-memory.
- Dispatch a mutation tool call (e.g.
create_entitiesoradd_observations) that acquires the lock viawithFileLock. - Terminate or stop the server process via SIGINT, SIGTERM, client disconnect, or container stop during the operation.
- Inspect the directory holding
memory.jsonl. - Attempt a subsequent write from another agent or container sharing the same graph file.
Expected behavior
The server should register signal handlers (SIGINT, SIGTERM) and exit cleanup hooks to remove any active lock file it currently holds, preventing orphaned lock files on abrupt shutdown.
Actual behavior
In Node.js, asynchronous finally blocks in withFileLock do not run when terminated by signals. Because src/memory registers no signal handlers (unlike src/everything/transports/stdio.ts), memory.jsonl.lock remains stranded on disk.
In multi-container or Docker environments where hostname !== os.hostname(), isLockOwnerDead returns false, forcing other agents to stall for up to 30–60 seconds before breaking the stale lock.
Additionally, in src/memory/Dockerfile, Node runs as PID 1 without STOPSIGNAL SIGINT, causing PID 1 to ignore SIGINT by default.
Already prototyped a fix?
Prompt for maintainer workflow:
"In src/memory/index.ts, track active lock files held by this process in an
activeLocksmap. On process exit and on SIGINT/SIGTERM, synchronously check if the lock file still contains our token, and if so, unlink it to avoid leaving stranded locks on abrupt shutdown. Add STOPSIGNAL SIGINT to src/memory/Dockerfile matching src/everything/Dockerfile. Add unit tests in file-lock.test.ts verifying active lock tracking and that cleanup leaves locks owned by another process intact."
Verification:
- Implemented and verified: all 231 tests in
src/memorypassing. - Working branch pushed for reference: https://github.com/Faris-as/servers/tree/memory-lock-signal-cleanup
Before you submit
- I searched existing issues and this is not a duplicate.
- This is not a security vulnerability report.
Activity
Faris-as commentedon Nov 6, 2026
Full implementation and tests are available on fork PR: Faris-as#1
cliffhall commentedon Nov 10, 2026
Triage: Priority Low (total 5)
buglabelBoard: Servers V2 (#43), Status
Incoming, awaiting maintainer review (no milestone yet).sahiln27042008-blip commentedon Nov 11, 2026
Hey @Faris-as @cliffhall — great catch in #5485 regarding orphaned
.lockfiles inserver-memoryon abrupt container termination.In distributed systems, relying on async
finallyblocks during POSIX signal unwinding is a classic lifecycle trap—Node.js terminates before the event loop unwinds the async finally, leaving stale locks that cause persistent deadlocks across container restarts.We build DISTRIB, a deterministic simulation gate for agent systems, and we test exactly this: simulating pod evictions and SIGTERM interrupts mid-transaction to verify lock lease reclamation. We tested a synchronous signal handler wrapper with
process.on('SIGINT')and heartbeat lease expirations (TTL-backed locks rather than purely manual unlinks) to make lock recovery completely crash-resilient.Happy to share our simulation harness or review your PR for free to ensure no edge-case lock leaks remain on abrupt client disconnects!