iOS Simulator panel crash-loops on attach: SIGABRT in CoreImage/Metal on the FBSimulatorControl BitmapStream thread

Status Closed — not planned
Maintainer reply None cached
Activity 1 comment · opened Aug 21, 2026 · closed Aug 21, 2026

What happened

mcp__Claude_Code_iOS_Simulator__control with action: "attach" opens the panel, then the claude-ios-sim helper aborts about 2.3 seconds later. Every following call returns:

Claude Code iOS Simulator is restarting after a crash. Try again in 1s.

It then crash-loops — three crash reports inside five seconds. Restarting the Claude desktop app does not help. An attach that returns success is a race against the stream thread starting, not a working panel.

Reproduces 100% here.

Environment

  • Claude desktop 1.34493.1, helper com.anthropic.claude.ios-sim
  • macOS 27.0 (26A5416b), Apple M2 Max, Metal 4
  • Xcode 26.6, simulator: iPhone 17 Pro on iOS 26.5

Where it dies

The faulting thread is com.facebook.FBSimulatorControl.BitmapStream — the live frame stream, not the screenshot action. It builds a CoreImage context on a Metal command queue; CoreImage loads its precompiled uber-function binary archive; Metal's own usage telemetry then constructs an NSArray containing a nil and throws, and the exception is uncaught because it happens inside a dispatch_once:

+[CIContext(Internal) internalContextWithMTLCommandQueue:options:]
CI::MetalContext::MetalContext(...)
CI::MetalContext::init(id<MTLCommandQueue>, char const*)
CI::new_uber_functions(CI::MetalContext const*)
CI::PrecompiledUberFunctions::PrecompiledUberFunctions(CI::MetalContext const*)
+[CIKernelLibrary(Internal) internalBinaryArchiveWithName:device:]
-[_MTLBinaryArchive initWithOptions:device:url:error:]
-[_MTLBinaryArchive loadFromURL:error:]
-[_MTLDevice recordBinaryArchiveUsage:]
__39-[_MTLDevice recordBinaryArchiveUsage:]_block_invoke
+[NSArray arrayWithObjects:count:]
-[__NSPlaceholderArray initWithObjects:count:]   <- throws, nil element
objc_exception_throw -> std::__terminate -> abort()

EXC_CRASH (SIGABRT), abort() called.

Ruled out

  • Not a general macOS/Metal fault on this machine. A ~15 line Swift program doing the same CIContext(mtlCommandQueue:) and rendering an image through it succeeds. CoreImage-on-Metal is otherwise healthy here.
  • Not a stale shader cache. Moving com.apple.metal and com.apple.metalfe aside reproduced the identical signature on a cold cache; both regenerate normally.
  • Not Rosetta. The crash report says cpuType: ARM-64, translated: False.
  • Not sandbox denial. The helper's entitlements dictionary is empty.

So it looks specific to how the helper constructs its CIContext on the BitmapStream thread, rather than to the host OS.

Suggested handling

Metal is throwing an Objective-C exception out of a dispatch_once in its own telemetry, which no caller can catch by ordinary means. The robust mitigation is to stop a Metal telemetry exception being able to take the whole helper down — build the frame path without CoreImage where possible, or isolate/guard the CIContext construction so a failure degrades the panel instead of aborting the process.

Workaround for anyone hitting this

Drive the simulator with XcodeBuildMCP instead — screenshot, snapshot_ui, tap, swipe all work, and snapshot_ui returns labelled element refs rather than raw coordinates.

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗