You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Running mlx_lm.server with Qwen3-Coder-30B-A3B-Instruct-8bit on a Mac Studio M3 Ultra (96GB) caused a full macOS kernel panic after the KV cache grew unboundedly during an agentic coding session (~58k+ tokens context). The system crashed and rebooted — not a process termination, but a kernel-level panic in IOGPUMemory.cpp.
System Information
Hardware: Mac Studio (Mac15,14) — Apple M3 Ultra, 28 cores (20P + 8E), 60 GPU cores, 96 GB unified memory
macOS: 26.3 (25D125)
Kernel: Darwin 25.3.0 (xnu-12377.81.4~5/RELEASE_ARM64_T6031)
Python: 3.12
mlx-lm: 0.30.6
mlx: 0.30.6
Model
mlx-community/Qwen3-Coder-30B-A3B-Instruct-8bit (~32GB on disk)
The MLX server process was consuming 83.23 GB of the 96 GB system at the time of the kernel panic.
Root Cause Analysis
mlx_lm.server starts by wiring ~75% of RAM via mx.set_wired_limit(max_recommended_working_set_size) — on a 96GB system, that's ~72GB. Wired memory cannot be swapped to disk.
macOS couldn't recover — because the memory was wired (locked in RAM), macOS's Jetsam OOM killer couldn't reclaim it. The GPU driver (IOGPUMemory.cpp) hit a "prepare count underflow" when it couldn't allocate memory, causing a kernel panic instead of a graceful process termination.
memoryPressure: false in the panic report shows that macOS didn't even detect memory pressure — the wired memory bypassed the normal memory pressure monitoring system entirely.
Add --memory-limit flag to mlx_lm.server — allow users to cap total memory usage via mx.metal.set_memory_limit(). The current default (wiring 75% of RAM) is dangerously aggressive for systems running other processes.
Reduce the default wired limit — mx.set_wired_limit(max_recommended_working_set_size) should not wire 75% of RAM by default. Consider 50-60%, or at minimum, make it configurable.
Add memory monitoring with graceful shutdown — the server should monitor its own memory usage and return an error response (e.g., HTTP 503) when approaching the limit, rather than growing until the kernel panics.
Document the risk — users should be warned that running large models (30B+) on systems with ≤128GB can cause kernel panics if context grows too large.
Summary
Running
mlx_lm.serverwith Qwen3-Coder-30B-A3B-Instruct-8bit on a Mac Studio M3 Ultra (96GB) caused a full macOS kernel panic after the KV cache grew unboundedly during an agentic coding session (~58k+ tokens context). The system crashed and rebooted — not a process termination, but a kernel-level panic inIOGPUMemory.cpp.System Information
Model
mlx-community/Qwen3-Coder-30B-A3B-Instruct-8bit(~32GB on disk)Steps to Reproduce
mlx_lm.server:/v1/chat/completionsrequests with growing conversation contextKernel Panic Details
Panic string:
Memory status at crash:
memoryPressurefalse(system didn't detect pressure!)Python/MLX process memory at crash:
The MLX server process was consuming 83.23 GB of the 96 GB system at the time of the kernel panic.
Root Cause Analysis
mlx_lm.serverstarts by wiring ~75% of RAM viamx.set_wired_limit(max_recommended_working_set_size)— on a 96GB system, that's ~72GB. Wired memory cannot be swapped to disk.The KV cache grows without bound —
mlx_lm.serverdoes not support--max-kv-size(see Feature Request: Add max-kv-size Support to MLX HTTP Server #615), so as the agentic tool sends longer and longer conversations, the KV cache keeps growing.Memory breakdown at crash:
macOS couldn't recover — because the memory was wired (locked in RAM), macOS's Jetsam OOM killer couldn't reclaim it. The GPU driver (
IOGPUMemory.cpp) hit a "prepare count underflow" when it couldn't allocate memory, causing a kernel panic instead of a graceful process termination.memoryPressure: falsein the panic report shows that macOS didn't even detect memory pressure — the wired memory bypassed the normal memory pressure monitoring system entirely.Suggested Fixes
Add
--max-kv-sizetomlx_lm.server(already requested in Feature Request: Add max-kv-size Support to MLX HTTP Server #615) — this is the most critical fix. Without a KV cache cap, memory grows unboundedly with context length.Add
--memory-limitflag tomlx_lm.server— allow users to cap total memory usage viamx.metal.set_memory_limit(). The current default (wiring 75% of RAM) is dangerously aggressive for systems running other processes.Reduce the default wired limit —
mx.set_wired_limit(max_recommended_working_set_size)should not wire 75% of RAM by default. Consider 50-60%, or at minimum, make it configurable.Add memory monitoring with graceful shutdown — the server should monitor its own memory usage and return an error response (e.g., HTTP 503) when approaching the limit, rather than growing until the kernel panics.
Document the risk — users should be warned that running large models (30B+) on systems with ≤128GB can cause kernel panics if context grows too large.
Related Issues
mlx_lm.serverdoes not support--max-kv-sizePanic Log
Key fields from panic-full-2026-02-12-011744.0002.panic
{ "bug_type": "210", "timestamp": "2026-02-12 01:17:44.00 -0300", "os_version": "macOS 26.3 (25D125)", "incident_id": "0BA6183D-4448-439B-B57E-EE3B2CD397AB" }Panic string:
Memory status:
{ "compressorSize": 47640, "compressions": 8141671, "decompressions": 4388400, "busyBufferCount": 0, "memoryPressureDetails": { "pagesWanted": 3027, "pagesReclaimed": 5807 }, "pageSize": 16384, "memoryPressure": false, "memoryPages": { "active": 466937, "throttled": 0, "fileBacked": 342561, "wired": 5251984, "purgeable": 69720, "inactive": 465071, "free": 973, "speculative": 54 } }Calculated:
MLX Python process: