[Desktop] iOS Simulator panel: claude-ios-sim crash-loops in Metal/CoreImage on macOS 27.0 beta — panel stuck on 'Attach a simulator'

Status Open
Maintainer reply None cached
Activity 14 comments · opened Jul 22, 2026

Summary

The iOS Simulator panel in the Claude desktop app cannot start its video stream on macOS 27.0 beta. The helper process claude-ios-sim (com.anthropic.claude.ios-sim, bundled at Claude.app/Contents/Helpers/Claude iOS Sim.app) crash-loops with an uncaught NSException (SIGABRT) while initializing a CoreImage CIContext, so the panel stays stuck on the "Attach a simulator so Claude can see your app" placeholder, and the MCP screenshot action fails with "Claude Code iOS Simulator is restarting after a crash."

The attach MCP action reports success and the simulator itself is healthy (apps install, launch, and screenshot fine via xcrun simctl), so this is host-side in the panel's capture/streaming pipeline.

Environment

  • Claude desktop app: 1.24012.1
  • macOS: 27.0 beta (build 26A5388g), Apple Silicon
  • Xcode 26.6, iOS Simulator runtimes 26.5 and 27.0
  • Booted device: iPhone 17 Pro (iOS 26.5)

Crash signature

lastExceptionBacktrace from ~/Library/Logs/DiagnosticReports/claude-ios-sim-*.ips (identical across ~6 crashes over one day):

CoreFoundation   __exceptionPreprocess
libobjc.A.dylib  objc_exception_throw
CoreFoundation   -[__NSPlaceholderArray initWithObjects:count:]   <- nil object inserted
CoreFoundation   +[NSArray arrayWithObjects:count:]
Metal            __39-[_MTLDevice recordBinaryArchiveUsage:]_block_invoke
libdispatch      _dispatch_once_callout
Metal            -[_MTLDevice recordBinaryArchiveUsage:]
Metal            -[_MTLBinaryArchive loadFromURL:error:]
Metal            -[_MTLBinaryArchive initWithOptions:device:url:error:]
CoreImage        +[CIKernelLibrary(Internal) internalBinaryArchiveWithName:device:]
CoreImage        CI::PrecompiledUberFunctions::PrecompiledUberFunctions(CI::MetalContext const*)
CoreImage        CI::MetalContext::init(id<MTLCommandQueue>, char const*)
CoreImage        +[CIContext(Internal) internalContextWithMTLCommandQueue:options:]
CoreImage        -[CIContext initWithMTLDevice:options:]

Termination: EXC_CRASH (SIGABRT), abort() called, thrown from __cxa_throw via _objc_terminate.

Looks like Metal's binary-archive usage recording gets a nil while building an NSArray on this OS build — i.e. an OS-beta incompatibility — but the helper turning that into a hard crash-loop (instead of falling back to a software/non-binary-archive CI context or surfacing an error in the panel) makes the whole feature unusable.

Steps to reproduce

  1. macOS 27.0 beta (26A5388g), Claude desktop 1.24012.1.
  2. Boot any iOS simulator (xcrun simctl boot <udid>).
  3. In a Claude Code session, use the iOS Simulator tool: attach succeeds and the panel opens.
  4. Panel never streams (stays on the attach placeholder); any screenshot action returns "restarting after a crash", and a new claude-ios-sim-*.ips crash report appears each time.

What I ruled out

  • Simulator/app health: xcrun simctl io <udid> screenshot and app install/launch all work.
  • iOS runtime version: same behavior regardless of 26.5 vs 27.0 runtimes (crash is host-side, before any device pixels).
  • Metal shader caches: deleting $(getconf DARWIN_USER_CACHE_DIR)/com.apple.metal and com.apple.metalfe and killing the helper did not change the signature.

Intermittently, after many helper restarts, one panel window did come up streaming — but new panel instances in the same session still land on the placeholder, so recovery is unreliable.

Expected

Either the panel streams on macOS 27 beta, or the helper catches the CI/Metal init failure and shows an actionable error in the panel instead of crash-looping behind a generic "Attach a simulator" placeholder.

Happy to share full .ips files on request.

View original on GitHub ↗

5 Comments

JayMcW99 · 1 month ago

Confirming this from a separate session — filed as #80257 before finding this one (closing mine as a dupe of this one).

Same symptoms: attach reports success every time, screenshot always returns "Claude Code iOS Simulator is restarting after a crash. Try again in 1s.", and xcrun simctl/xcodebuild build/xcodebuild test were unaffected throughout — matches your "host-side in the panel's capture/streaming pipeline" conclusion exactly.

One data point to add: a full macOS restart (not just the helper/Claude app) did not clear it. After rebooting the Mac entirely and relaunching Claude, the very first attach/screenshot attempt reproduced the identical crash-loop immediately — no "many helper restarts" needed to reach the bad state, and no intermittent successful stream like you saw. This is consistent with your theory that it's a deterministic OS-beta/Metal incompatibility rather than corrupted cache/process state, since a full reboot clears all of that and it still failed on the first try.

Also ruled out on my end before finding this issue: multiple simultaneously-booted simulators, and Simulator.app (the GUI) not being running — neither was the cause; reproduces with exactly one cleanly booted device and Simulator.app confirmed running via ps.

oyeeamir · 1 month ago

Confirming on a third machine, with one data point that rules out a whole class of explanations.

Environment: Claude Desktop 1.24012.1, macOS 27.0 beta (26A5388g), Apple M5, Xcode 27.0 beta (27A5209h), iOS 27.0 runtime (24A5370g). Identical crash signature — -[_MTLDevice recordBinaryArchiveUsage:]+[NSArray arrayWithObjects:count:] nil insert, reached via FBSurfaceImageGenerator.image()-[CIContext initWithOptions:]. 9 crashes in a few minutes. Note this reproduces on M5 / Xcode 27 beta, where #80288 is M4 Pro / Xcode 27 release and this report is Xcode 26.6 — so it's independent of GPU generation and Xcode version.

New: this is not a general macOS 27 Metal/CoreImage fault. I built a standalone Swift binary exercising the identical path (CIContext(options: nil)createCGImage). It succeeds every time on the same machine, under every condition I could match to the helper:

| Condition | Result |
|---|---|
| CIContext(options: nil) + createCGImage | works |
| CIContext(mtlCommandQueue:) | works |
| With CoreSimulator.framework + SimulatorKit.framework dlopened first | works |
| With Metal shader cache (…/C/com.apple.metal/<gpu>) moved aside | works |
| Under scrubbed env (env -i, no TMPDIR/HOME) | works |

The fault is specific to the claude-ios-sim process, not to CoreImage on this OS. Combined with the reboot test above, that also rules out corrupt shader cache and missing temp dir — the two things triage normally reaches for first.

Possible direction: the helper is signed with an empty entitlements dictionary (codesign -d --entitlements :- returns {}) and the abort is inside Metal's binary-archive path. I couldn't verify whether a missing GPU/Metal entitlement or a nil archive URL is the trigger without re-signing the app, but it may be worth checking.

Control plane vs capture plane: with the #80288 symlink workaround applied, attach succeeds and tap is delivered correctly to a booted iPhone 17 Pro. Only frame capture crashes.

robert-811 · 1 month ago

Fourth machine confirming, plus a sandbox lead and one adjacent bug your environment can't hit.

Environment: Claude Desktop 1.24012.1, macOS 27.0 (26A5388g), M4 Pro, Xcode 27.0 beta 27A5228h, iOS 27.0 runtimes 24A5380i and 24A5390f. Identical backtrace through FBSurfaceImageGenerator.image()-[CIContext initWithOptions:]_MTLBinaryArchive loadFromURL:recordBinaryArchiveUsage: → nil into +[NSArray arrayWithObjects:count:]. Filed separately as #80288 before finding this one.

Combined with @oyeeamir's M5 / Xcode 27 beta 27A5209h and your Xcode 26.6, that's three GPU generations and three Xcode builds with one signature.

Additionally ruled out here:

  • Both iOS 27 runtime builds — reproduces on 24A5380i and on 24A5390f, including on a device created fresh, never booted before.
  • xcode-select state — reproduced with it pointing at a stale path and after correcting it.
  • Panel/video state entirely — reproduces with the panel fully detached, calling screenshot headlessly. Since no stream is running, this isn't in the encoder: the H.264/JPEG encoding toggle is a red herring (I burned time on it). The dispatch_once frame shows it's one-time Metal init on the connect path, before encoding is consulted.
  • Endpoint security (Sophos) — the crash is a self-inflicted SIGABRT from an uncaught ObjC exception with a full in-process backtrace, not an external SIGKILL.
  • Precreating Metal cache dirs~/Library/Caches/com.apple.metal, com.apple.metalfe, and ~/Library/Caches/com.anthropic.claude.ios-sim/com.apple.metal all made no difference. $DARWIN_USER_CACHE_DIR/com.apple.metal already existed with populated per-GPU subdirs.

Possible mechanism. The helper's sandbox profile (Claude.app/Contents/Resources/claude-ios-sim.sb) is (deny default) and grants file-write* to only CORESIM_HOME, CORESIM_LOGS, DARWIN_TMP and /private/var/tmp. There's a param for the Darwin temp dir but **none for the Darwin user cache dir, and no rule for ~/Library/Caches** — where Metal's shader cache lives. A commenter on #80288 reports MTLGetShaderCachePath returning nil when the helper's cache-dir mkdir fails, which fits: CoreImage's internalBinaryArchiveWithName: needs that path, gets nil, and nil goes into the array.

That would also explain @oyeeamir's standalone-binary result — an unsandboxed process writes the cache fine, so the fault only appears under the helper's confinement. Stated as a hypothesis: I see no sandbox violation reports on disk or in the unified log for this process, so it isn't directly confirmed.

Separate bug, newer Xcode 27 seeds only (26.6 machines won't see it, and @oyeeamir's 27A5209h apparently didn't either — so it seems to have landed between 27A5209h and 27A5228h): FBControlCore loads $DEVELOPER_DIR/Library/PrivateFrameworks/SimulatorKit.framework, but Xcode 27 removed that directory — SimulatorKit, DVTFoundation, DVTDeviceFoundation et al. now live in Contents/SharedFrameworks. attach fails outright before any Metal code runs. Local workaround, which does work:

ln -s ../../SharedFrameworks /Applications/Xcode.app/Contents/Developer/Library/PrivateFrameworks

Details in #80288. Anyone on a seed with the new layout hits that first and never reaches this crash.

---

Correction (edited): I originally wrote Xcode 27.0 release (not beta). Wrong — it's Xcode 27.0 beta 27A5228h; the bundle had been renamed from Xcode-beta.app locally so the path looked like a release install. The cross-environment point is unchanged, but the correct framing is three different builds, not a release-vs-beta split.

robert-811 · 1 month ago

Update for anyone landing here: both bugs now have verified one-line workarounds, and the Metal one has a full root-cause analysis in #80472.

# Bug 1 — Xcode 27 moved SimulatorKit/DVT* to Contents/SharedFrameworks  (#80180, #79991)
ln -s ../../SharedFrameworks /Applications/Xcode.app/Contents/Developer/Library/PrivateFrameworks

# Bug 2 — macOS 27 beta: Metal's per-bundle shader-cache dir the sandbox can't create  (#80472)
mkdir -p "$(getconf DARWIN_USER_CACHE_DIR)/com.anthropic.claude.ios-sim/com.apple.metal"

Verified on macOS 27.0 beta (26A5388g), M4 Pro, Xcode 27 beta 27A5228h, iOS 27.0 24A5380i: attach, screenshot and tap all work afterwards. The panel had been 100% broken.

Two corrections to what I wrote earlier in this thread, since they'd waste other people's time:

  1. I suggested the encoding dropdown (H.264 → JPEG) as a possible dodge. It isn't — the crash is one-time Metal init on the connect path and reproduces with the panel fully detached, no stream running. Ignore that suggestion.
  2. My cache-dir attempts under ~/Library/Caches/… all failed. It is specifically $(getconf DARWIN_USER_CACHE_DIR) — the C/ folder in /var/folders/.... The two are easy to conflate and only the latter works.

I also bisected the fix in #80472: of the three directories originally published, only com.apple.metal is required, and Metal never writes into it — it just has to exist.

krisniles · 1 month ago

Confirming on a fifth machine, with one data point the thread doesn't have yet: still reproduces on Claude Desktop 1.24012.9 (thread so far only lists 1.24012.1).

Environment: Claude Desktop 1.24012.9, macOS 27.0 beta (26A5388g), Apple Silicon (J516s), Xcode 26.6, iPhone 17 Pro (iOS 26.5).

  • Identical signature: uncaught NSInvalidArgumentException "attempt to insert nil object from objects[0]" in __39-[_MTLDevice recordBinaryArchiveUsage:]_block_invoke, faulting thread com.facebook.FBSimulatorControl.BitmapStream. Helper aborts ~1–2 s after attach reports success; 11 identical .ips files over an hour of crash-looping.
  • Reproduces with one booted device and with two (iPad Pro 13" additionally booted) — device count is irrelevant.
  • Xcode 26.6 here, so SimulatorKit loads from the old PrivateFrameworks path — only the Metal bug applies on this machine; no symlink workaround needed.
  • Extra observation re: the #80472 root cause: during the crash window sandboxd logged no file-system denials for the helper — only user-preference-read denies (kCFPreferencesAnyApplication, com.apple.coresimulator) ~1 s before the abort. If the shader-cache mkdir is being denied, it isn't surfacing as a reported sandbox violation on this build.
  • Possibly relevant: the helper's Info.plist ships no CFBundleVersion/CFBundleShortVersionString (crash headers show empty app_version/build_version), in case Metal's usage-telemetry array also folds in bundle-version fields.

Workaround verified here as well:

mkdir -p "$(getconf DARWIN_USER_CACHE_DIR)/com.anthropic.claude.ios-sim/com.apple.metal"

Immediately after creating the dir: attach, live panel streaming, and headless screenshot all work, helper stays alive, no new .ips. No app restart needed — the next helper respawn picked it up. Happy to attach the .ips files if useful (stack is byte-for-byte the OP's).

Showing cached comments. Read the full discussion on GitHub ↗