fix: MCP null args hang, repair infinite recursion, OOM on large files#399
fix: MCP null args hang, repair infinite recursion, OOM on large files#399milla-jovovich merged 3 commits intomainfrom
Conversation
Three critical bugfixes: 1. MCP server hangs on null arguments (#394) — `params.get("arguments", {})` returns None when JSON has `"arguments": null`. Changed to `or {}`. 2. cmd_repair infinite recursion (#395) — trailing slash on palace_path caused backup_path to be inside the source dir. Strip trailing sep. 3. OOM on large transcript files (#396) — split_mega_files.py and normalize.py load entire files into memory. Added 500MB safety limit with clear skip/error messages. Closes #394, #395, #396.
1f43502 to
a0056dc
Compare
milla-jovovich
left a comment
There was a problem hiding this comment.
I've taken a look and ran it through CLI. Three small, targeted fixes, each one matches the bug it claims to close:
- #394 null args hang —
params.get("arguments") or {}correctly coerces bothNoneand missing-key to{}so the downstream.items()call can't crash - #395 repair infinite recursion —
palace_path.rstrip(os.sep)before computingbackup_pathprevents the<path>/.backuppath from being a child of the source dir. Good catch. - #396 OOM on large files — 500 MB guard added in
normalize.py,split_file, and the main scan loop insplit_mega_files.pywith clear skip messages. Clean.
One minor note (not blocking): in normalize.py the IOError raised on the size check sits inside the existing try/except OSError block — and IOError is an alias for OSError in Python 3, so the existing handler will catch it and format as a generic "Cannot read file" message, which might obscure the specific "too large" wording. Worth raising before the open() call instead, or letting it propagate. Small thing.
Also noticed the CI coverage threshold dropped from 85 → 80 in ci.yml. Fine if intentional; heads-up if not.
Everything else looks right to me. 💜
PR Review: fix: MCP null args hang, repair infinite recursion, OOM on large filesExecutive Summary
Affected Areas: Business Impact: Prevents MCP client hangs (server availability), disk exhaustion during repair (data safety), and OOM crashes on large files (stability). Flow Changes: Ratings
PR Health
Guidelines Compliance
High Priority Issues(Must fix before merge) [Bug] #1:
|
…ixes - Move file size check before try block so IOError propagates cleanly (not caught by the except OSError handler below it) - Wrap os.path.getsize in its own try/except to preserve existing test_normalize_io_error behavior on missing files - Add test_normalize_rejects_large_file (mocked getsize) - Add test_null_arguments_does_not_hang (#394) - Add test_cmd_repair_trailing_slash_does_not_recurse (#395) 532 tests pass locally, 0 regressions.
|
thanks @bgauryy for the reviews! and please thank Octocode from Lu.✨ |
|
@milla-jovovich my pleasure 🙏 |
`params.get("arguments", {})` returns None when the JSON payload
contains `"arguments": null` (not just when the key is absent). The
subsequent type-coercion loop calls `.items()` on None and crashes
the request, leaving MCP clients hanging.
Ported from upstream 0720fb8 (PR MemPalace#399, fixes MemPalace#394),
by @bensig.
Co-Authored-By: bensig <[email protected]>
Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Both normalize.normalize() and split_mega_files slurp entire transcript files into memory. Pathologically large inputs can OOM the process. Add a 500 MB ceiling with a clear skip/error message at each entry point: normalize() raises IOError, split_file() prints SKIP and returns [], and the main scan loop also skips oversized files before attempting to read them. Ported from upstream 0720fb8 (PR MemPalace#399, fixes MemPalace#396), by @bensig. Co-Authored-By: bensig <[email protected]> Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Summary
Three critical bugfixes from Igor's issue tracker:
MCP server hangs on null arguments (MCP server hangs when client sends null arguments — unhandled AttributeError in request handler #394) — When a client sends
"arguments": null,params.get("arguments", {})returnsNone(not{}), causingAttributeErroron.items()with no error response. Client hangs indefinitely. Fix:params.get("arguments") or {}.cmd_repair infinite recursion fills disk (cmd_repair infinite recursion when palace_path has trailing slash — fills disk #395) — When
palace_pathhas a trailing slash,backup_path = palace_path + ".backup"creates the backup inside the source dir, causingshutil.copytreeto recursively copy into itself until disk is full. Fix:palace_path.rstrip(os.sep).OOM on large transcript files (OOM crash on large transcript files — split_mega_files.py and normalize.py load entire file into memory #396) —
split_mega_files.pyloads entire files into memory twice, andnormalize.pydoes it once. Multi-GB Slack/ChatGPT exports cause MemoryError. Fix: 500MB file size guard with clear skip/error messages.Closes #394, #395, #396.
Test plan
{"method": "tools/call", "params": {"name": "mempalace_status", "arguments": null}}— should return result, not hangmempalace repairwithpalace_path = "~/.mempalace/palace/"(trailing slash) — should not recursemempalace spliton a file >500MB — should skip with message, not OOM