Persistent-service crash loop on macOS 26 (Darwin 27): PyTorch MPS backend aborts on IOGPUMetalCommandBuffer during embedder/kompress model load
Description
The persistent-service deployment enters a hard crash loop on macOS 26 (Darwin 27). It restarts roughly every 60 seconds continuously (200+ crashes observed in one session). Each crash is a native Metal assertion abort during PyTorch MPS model load, not a Python exception, so nothing in headroom can catch or retry around it.
Root cause: the generated deployment config sets both HEADROOM_EMBEDDER_RUNTIME=pytorch_mps (memory embedder, headroom/memory/adapters/embedders.py) and HEADROOM_KOMPRESS_BACKEND=pytorch_mps (compression model, headroom/transforms/kompress_compressor.py), forcing PyTorch onto the Apple Silicon MPS/Metal backend. HEADROOM_KOMPRESS_BACKEND=pytorch_mps has a try/except around load-time validation that falls back to ONNX/CPU on failure, but this crash is a native Metal abort that kills the whole process before Python gets a chance to catch it, so the fallback path never runs. HEADROOM_EMBEDDER_RUNTIME=pytorch_mps has no fallback at all.
This looks tied to a macOS 26 upgrade (crashes started the day after upgrading) — PyTorch's MPS backend commonly lags behind new macOS majors before Apple/PyTorch re-validate compatibility.
To Reproduce
Steps to reproduce the behavior:
- Install headroom with the
persistent-servicepreset on Apple Silicon running macOS 26 (Darwin 27), withHEADROOM_EMBEDDER_RUNTIME=pytorch_mpsand/orHEADROOM_KOMPRESS_BACKEND=pytorch_mpsset (this is the default in the generatedrun-headroom.sh/ensure-headroom.shfor a persistent-service deployment) - Start/restart the deployment:
headroom install restart - Watch
~/.headroom/deploy/default/runner.log— the proxy starts, then aborts within seconds during embedder/kompress model load; launchd respawns it and it crashes again on a ~60s cycle
Expected Behavior
The proxy should either load the model successfully, or fail gracefully by falling back to a CPU/ONNX backend, without entering an unrecoverable crash loop that leaves the deployment permanently unhealthy.
Actual Behavior
The process aborts with a native Metal assertion immediately after Starting proxy server..., before the proxy becomes healthy. headroom install status alternates between running/healthy: yes and healthy: no as launchd keeps respawning the process. Every client routed through the proxy (e.g. Claude Code via ANTHROPIC_BASE_URL) intermittently sees API Error: Connection lost mid-response when a request lands mid-crash.
Code Sample
# Not a client-code issue — the crash happens inside the headroom proxy's
# own model-loading path (memory embedder / kompress compressor), triggered
# simply by running the persistent-service deployment with the pytorch_mps
# backend selected. No user code is involved.
Error Output
2026-09-15 21:08:18.176 python3[52375:4668384] failed assertion _status < MTLCommandBufferStatusCommitted at line 323 in -[IOGPUMetalCommandBuffer setCurrentCommandEncoder:]
Starting proxy server...
2026-09-15 21:09:23.790 python3[55198:4677048] failed assertion _status < MTLCommandBufferStatusCommitted at line 323 in -[IOGPUMetalCommandBuffer setCurrentCommandEncoder:]
Starting proxy server...
2026-09-15 21:10:27.087 python3[60362:4687421] failed assertion _status < MTLCommandBufferStatusCommitted at line 323 in -[IOGPUMetalCommandBuffer setCurrentCommandEncoder:]
Starting proxy server...
(repeats on a ~60s cycle, 200+ occurrences in the log)
Environment
- Headroom version: 0.37.0
- Python version: 3.13.13
- OS: macOS 26.0 (Darwin 27.0.0, build 26A428), Apple Silicon (arm64)
- LLM Provider: Anthropic
Additional Context
- torch version: 2.14.0
- Deployment:
persistent-servicepreset, launchd-managed (com.headroom.default) - Suggested fix: detect repeated rapid restarts and auto-downgrade
HEADROOM_EMBEDDER_RUNTIME/HEADROOM_KOMPRESS_BACKENDtocpu/onnxfor that deployment, or at least surface an actionable error viaheadroom doctorinstead of a silent restart cycle. Also worth reconsidering defaulting persistent-service deployments topytorch_mpson macOS given how brittle Metal/MPS compatibility is across OS versions. - Workaround: manually setting
HEADROOM_EMBEDDER_RUNTIME=cpuandHEADROOM_KOMPRESS_BACKEND=onnx(or unset, sinceautoprefers ONNX CPU) in the deployment'srun-headroom.sh/ensure-headroom.sh, thenheadroom install restart, resolves it.
Source: headroomlabs-ai/headroom