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

Status Fixed / completed
Maintainer reply None cached
Activity 20 comments · opened Jul 22, 2026 · closed Sep 15, 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 ↗

20 Comments

JayMcW99 · 2 months 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 · 2 months 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 · 2 months 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 · 2 months 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 · 2 months 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).

heznpc · 2 months ago

Hitting the exact same crash-loop on macOS 27.0 beta (26A5388g) — caught it live with log stream running alongside the panel, which adds a bit more detail.

Setup: MacBook Air, Mac16,12 (Apple Silicon), macOS 27.0 beta 26A5388g, Xcode 26.3, iOS 26.3 simulator runtime, Claude desktop 1.26832.0.

claude-ios-sim does launch (so it's not gated off before starting) and dies almost immediately. The live log around each crash shows a batch of sandbox denials right before it, repeated for claude-ios-sim[<pid>]:
Couldn't read values in CFPrefsPlistSource<...> (Domain: kCFPreferencesAnyApplication, ...): accessing these preferences requires user-preference-read or file-read-data sandbox access
(not claiming this causes the crash — just noting it shows up right before, every time.)

Edit: an earlier version of this comment said no .ips was landing on disk. That was wrong — one did get written (claude-ios-sim-2026-08-10-154234.ips), I just hadn't looked in the right window. Its backtrace is identical to this issue's, down to the crashing dispatch queue:

Exception: EXC_CRASH / SIGABRT, thread on queue "com.facebook.FBSimulatorControl.BitmapStream"
objc_exception_throw
-[__NSPlaceholderArray initWithObjects:count:]   <- nil object inserted
+[NSArray arrayWithObjects:count:]
__39-[_MTLDevice recordBinaryArchiveUsage:]_block_invoke
-[_MTLDevice recordBinaryArchiveUsage:]
-[_MTLBinaryArchive loadFromURL:error:]
-[_MTLBinaryArchive initWithOptions:device:url:error:]
+[CIKernelLibrary(Internal) internalBinaryArchiveWithName:device:]
CI::PrecompiledUberFunctions::PrecompiledUberFunctions(CI::MetalContext const*)
CI::MetalContext::init(...)
+[CIContext(Internal) internalContextWithMTLCommandQueue:options:]
-[CIContext initWithMTLDevice:options:] / +[CIContext contextWithMTLDevice:options:]

A couple of details from the actual report that weren't in the original post:

  • CoreImage.framework reports CFBundleShortVersionString: 27.0.0 (build 1663) — its own version string matches the OS beta number, so this looks like it could be a CoreImage/Metal regression specific to the beta build rather than anything in Claude's bundled code. Metal.framework is 382.5.
  • Crashing binary's code signing team ID is Q6L2SF6YDW.
  • It's consistently the com.facebook.FBSimulatorControl.BitmapStream queue that dies — i.e. specifically the screen-capture/streaming path, not simulator control in general.

Each restart gets a new PID, confirming this cycles rather than sticking.

Also confirming what's already ruled out here: xcrun simctl (install/launch/screenshot) and XCUITest (real synthesized taps) work perfectly against the same booted device throughout — only the live-streaming panel is affected.

Have a ~13s screen recording (panel + a live filtered log stream side by side) showing the click → black screen → "restarting after a crash" → repeat cycle, matched against the log in real time, plus the full .ips. Happy to attach either if useful.

willsigmon · 1 month ago

Confirming still present on a newer Desktop build and newer macOS seed, with a direct verification of the #80472 mechanism.

Environment: Claude Desktop 1.30096.5, macOS 27.0 beta 26A5406e, M4 Max (Mac16,13), Xcode 26.6 (17F113) selected; also Xcode 27 beta 4 installed but not selected. iOS 26.5 runtime, iPhone 17 booted.

Symptom: identical signature — FBSurfaceImageGenerator.image() → -[CIContext initWithOptions:] → _MTLBinaryArchive loadFromURL: → recordBinaryArchiveUsage: → nil into +[NSArray arrayWithObjects:count:], SIGABRT. Reproduced on screenshot with the panel detached (no video stream), so it is the one-time Metal init on the capture path, not the encoder.

Verification of the seatbelt/cache theory: I drove the real helper binary over its stdio protocol (describe / startVideo / screenshot / stopVideo) from a shell in four modes — bare, under sandbox-exec -f claude-ios-sim.sb, under Helpers/disclaimer, and disclaimer+sandbox exactly as the app spawns it. All four worked, including 200 KB PNG screenshots and bgra + h264 frames. The bare run created $(getconf DARWIN_USER_CACHE_DIR)/com.anthropic.claude.ios-sim/com.apple.metal/archiveUsage.db (timestamp matches to the second). From that moment the app-spawned sandboxed helper stopped crashing — zero further .ips reports, panel attach + screenshot succeed. Note the sandboxed runs in my test only passed because the bare run had already seeded the dir; before that, the app-spawned helper crashed on every attempt.

So the fix is what #80472 says: claude-ios-sim.sb needs file-write* on the helper's Metal cache subtree (DARWIN_USER_CACHE_DIR/com.anthropic.claude.ios-sim), or the helper should pre-create it before Metal init. The mkdir -p workaround from that thread is the user-side equivalent.

One adjacent observation for triage: with the crash cleared, the tool surface works, but the renderer is launched with "iosSimulator":{"status":"unsupported","reason":"iOS Simulator is disabled by its rollout flag"} on this account/build, so the visible pane may still not render even after the helper is healthy — worth separating "helper crash" from "panel not shown" reports.

heznpc · 1 month ago

Confirming @willsigmon's workaround on a different hardware/version combo — my earlier report in this thread, now resolved by the mkdir alone.

Environment: MacBook Air M4 (Mac16,12), macOS 27.0 beta 26A5388g, Claude Desktop 1.26832.0, Xcode 26.3, iOS 26.3 simulator runtime, iPhone 17 Pro booted.

  • Before: $(getconf DARWIN_USER_CACHE_DIR)/com.anthropic.claude.ios-sim did not exist at all, and every attach/screenshot crash-looped as described above.
  • Applied only mkdir -p "$(getconf DARWIN_USER_CACHE_DIR)/com.anthropic.claude.ios-sim/com.apple.metal" — no restarts, no other changes.
  • After: attach, screenshot, and tap via the MCP tool surface all work immediately and repeatedly. First successful panel capture on this machine since the issue started.

So the seatbelt/cache mechanism reproduces across two quite different setups (M4 Max/26A5406e/Desktop 1.30096.5/Xcode 26.6 vs M4 Air/26A5388g/Desktop 1.26832.0/Xcode 26.3) — consistent with a structural sandbox-profile omission rather than anything version-specific.

Also matching the adjacent observation: on this account/build the renderer still reports "iosSimulator": {"status": "unsupported", "reason": "iOS Simulator is disabled by its rollout flag"}, so the tool surface works while the visible pane may not — +1 for triaging "helper crash" and "panel not shown" as separate issues.

andrastar-ai · 1 month ago

Still reproduces on a fully-current stack — every component here is newer than anything else in this thread, so the sandbox-profile omission is still shipping.

Environment: Claude Desktop 1.32885.1, macOS 27.0 beta 26A5416b, M5 Pro (Mac17,9), Xcode 27.0 beta 27A5237l (only Xcode installed, and selected), iOS 27.0 runtime 24A5408d, iPhone 17 Pro booted.

For comparison the newest previously reported here was Desktop 1.30096.5 / macOS 26A5406e / Xcode 26.6 (@willsigmon, Aug 17) — so this adds a newer Desktop build, a newer macOS seed, a newer Xcode beta, a newer iOS runtime, and a GPU generation (M5 Pro) not yet represented.

Symptom: identical signature. The exceptionReason key from the .ips (the crash viewer doesn't surface this, and I didn't see it quoted in full upthread):

NSInvalidArgumentException
*** -[__NSPlaceholderArray initWithObjects:count:]: attempt to insert nil object from objects[0]

reached via SimulatorBridge.screenshot(udid:) → FBSurfaceImageGenerator.image() → -[CIContext initWithOptions:] → CI::new_uber_functions → -[_MTLBinaryArchive loadFromURL:error:] → -[_MTLDevice recordBinaryArchiveUsage:] → dispatch_once → SIGABRT.

Before/after, single variable changed:

  • Before: $(getconf DARWIN_USER_CACHE_DIR)/com.anthropic.claude.ios-sim did not exist at all. Every attach/screenshot produced a fresh .ips — one per call, confirmed by matching timestamps to the second.
  • Applied only mkdir -p "$(getconf DARWIN_USER_CACHE_DIR)/com.anthropic.claude.ios-sim/com.apple.metal". No app restart, nothing else touched.
  • After: attach and screenshot both succeed immediately and repeatedly, zero new crash reports.
  • Confirming @robert-811's bisect: the com.apple.metal directory is still empty afterwards. Metal never writes into it — it only has to exist.

Reading the profile on this build lines up with #80472: in Claude.app/Contents/Resources/claude-ios-sim.sb the (allow file-write* …) block (~line 144) grants DARWIN_TMP and /private/var/tmp, with no rule for the Darwin user cache dir — so the sandboxed helper can't create its own per-bundle Metal cache directory, and Metal aborts rather than degrading.

One behavioural detail I didn't see stated explicitly upthread: the crash is confined to the image path. While the helper was still crash-looping, non-image actions worked perfectly — button HOME and tap both returned success against the booted device and visibly took effect (verified out-of-band with xcrun simctl io <udid> screenshot, which also succeeded throughout at full resolution in ~0.5s). So pre-fix the tool surface is still usable for driving a simulator; only capture is dead. That also makes a decent workaround for anyone who can't run the mkdir: drive with the MCP tool, capture with simctl (mind the units — taps are in points, simctl PNGs are in pixels, 3× on this device).

Related: the error string "Claude Code iOS Simulator is restarting after a crash. Try again in 1s." implies transient recovery, but each retry re-crashes deterministically and it never recovers. Wording that suggests a persistent failure — or surfacing the underlying exception — would have saved a fair amount of digging.

Also matching the earlier observation: this account/build still reports "iosSimulator":{"status":"unsupported","reason":"iOS Simulator is disabled by its rollout flag"} in the renderer arguments, yet attach does open a panel and capture works post-fix.

n0ah37 · 1 month ago

Adding a negative result on the mkdir workaround, on a newer macOS seed than anything above, plus four things ruled out with evidence.

Environment: Claude Desktop 1.34493.1, macOS 27.0 beta 26A5416b, M2 Max, Xcode 26.6 (selected, and the only Xcode installed — so Bug 1 / SimulatorKit relocation is not in play here), iOS 26.5 runtime, iPhone 17 Pro booted.

Identical signature to this thread: -[_MTLDevice recordBinaryArchiveUsage:] → +[NSArray arrayWithObjects:count:] nil insert, reached via CI::MetalContext::init → new_uber_functions → _MTLBinaryArchive loadFromURL:, uncaught inside a dispatch_once, SIGABRT. Faulting thread com.facebook.FBSimulatorControl.BitmapStream. Three crashes in five seconds on retry.

The mkdir workaround does not resolve it on 26A5416b

$ ls -ld $(getconf DARWIN_USER_CACHE_DIR)/com.anthropic.claude.ios-sim
ls: ...: No such file or directory          # absent, as described upthread
$ mkdir -p $(getconf DARWIN_USER_CACHE_DIR)/com.anthropic.claude.ios-sim
$ pkill -f claude-ios-sim                    # then attach again

After that: the directory stays empty — nothing is ever written into it — and the helper crashes with the identical backtrace. So on this build the missing directory looks like a symptom rather than the cause.

Four things ruled out here

  1. Not a general macOS/Metal fault. A ~15-line Swift program doing the same CIContext(mtlCommandQueue:) and rendering an image through it succeeds on this machine. CoreImage-on-Metal is healthy outside the helper. This is worth stressing because the OS beta is in two of these issue titles — the beta alone is not sufficient to cause it.
  2. 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.
  3. Not Rosetta. The crash report says cpuType: ARM-64, translated: False.
  4. Not a sandbox denial — at least not a logged one. codesign -d --entitlements on the helper returns an empty entitlements dict (no App Sandbox), and log show over the crash window shows no sandbox deny for this process. That does not disprove the shader-cache-directory theory, but it does mean the "sandbox can't create the dir" framing doesn't fit this helper build.

One clarification that may help triage

The crash is not in the screenshot action. It is on the BitmapStream thread, ~2.3s after attach. attach returning success is a race against that thread starting, which is why it is sometimes reported as "attach works, screenshot fails". Consistent with that: tap and swipe work reliably even while streaming is broken, since they never touch CoreImage. That makes a usable stopgap — drive input through the MCP tap/swipe actions and take images with xcrun simctl io <udid> screenshot.

n0ah37 · 1 month ago

The mkdir workaround needs one more level than the version circulating in this thread, and it fixed the panel here once corrected. Posting because the short form is what people are copying, and on its own it does nothing.

Environment: Claude Desktop 1.34493.1, macOS 27.0 beta 26A5416b, M2 Max, Xcode 26.6 (only Xcode installed and selected, so the SimulatorKit relocation is not in play), iOS 26.5 runtime.

What failed

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

Directory created, helper restarted — identical crash, and the directory stayed completely empty. Nothing was ever written into it.

What worked

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

Panel attaches, streams, and screenshots normally. Zero crashes since. Metal is now populating that directory.

Why the extra level matters

#80472's analysis has it right, and the answer is in the path it quotes: $(getconf DARWIN_USER_CACHE_DIR)/<bundleID>/com.apple.metal/.... copyCacheMainFolder("com.apple.metal", create: true) has to create the com.apple.metal child, not the bundle-ID folder. The seatbelt profile denies mkdir on both, so pre-creating only the parent leaves the exact mkdir that fails still failing — MTLGetShaderCachePath() returns nil and the unguarded +[NSArray arrayWithObjects:count:] throws as before.

Sanity check that makes it obvious: every other GPU-using app on the machine already has both levels, e.g.

$(getconf DARWIN_USER_CACHE_DIR)/com.1password.1password/com.apple.metal

The helper was the only one missing them, because it is the only one that cannot create them itself.

Two notes for anyone landing here

  • DARWIN_USER_CACHE_DIR lives under /var/folders/... and is cleaned periodically, so this workaround is not necessarily permanent — if the panel starts crash-looping again, check whether the directory is still there before assuming a regression.
  • The crash is on the BitmapStream thread, ~2s after attach, not in the screenshot action. An attach that returns success is a race against that thread starting. Related and useful while broken: tap and swipe never touch CoreImage and keep working, so input through the MCP actions plus xcrun simctl io <udid> screenshot is a complete stopgap.

The real fix is still on the Anthropic side — file-write* on the helper's Metal cache subtree in claude-ios-sim.sb, as #80472 proposed.

dazza321 · 1 month ago

Independent confirmation + verified minimal fix, tying together what's spread across #80472 (closed as dup of this) and #88504.

Environment: macOS 27.0 beta 26A5388g, MacBook Air M3, Claude desktop (packaged), Xcode 26.3 (17C519).

Root cause (same crash as OP; verified by driving the shipped claude-ios-sim binary directly over its stdio protocol against a booted device):

  • The seatbelt profile Claude.app/Contents/Resources/claude-ios-sim.sb allows file-write* only on CORESIM_HOME, CORESIM_LOGS, DARWIN_TMP, and /private/var/tmp.
  • On macOS 27, CoreImage's Metal context init loads the precompiled uber-shader archive; Metal's -[_MTLDevice recordBinaryArchiveUsage:] needs the per-user shader cache under DARWIN_USER_CACHE_DIR (the …/C/ sibling of the allowed …/T/). With that write denied, a nil ends up in +[NSArray arrayWithObjects:count:] → uncaught NSInvalidArgumentException → SIGABRT. (#80472 pins the nil to MTLGetShaderCachePath().)

Causality A/B/C (same helper binary, same env, same booted iPhone 17 Pro sim, describe → screenshot):

  1. Spawned with the app's exact sandbox-exec line → describe OK, screenshot SIGABRT, 100%.
  2. Unsandboxed → screenshot returns a valid PNG, 100%.
  3. Sandboxed + one appended rule → valid PNG, 100%:
(allow file-write* (subpath "/private/var/folders/<user-hash>/C/com.apple.metal"))

After patching the shipped profile: panel attaches and streams, repeated screenshots/taps/HOME all work, helper stays resident, zero crashes since (was 27+ identical .ips since the beta landed).

Suggested fix: same as #88504 — pass a DARWIN_CACHE param from the sidecar spawn code (like the existing DARWIN_TMP) and allow file-write* on it (or scope to its com.apple.metal / per-bundle subpaths per #80472). Also worth an ObjC exception guard around the FBSimulatorControl render call so future OS drift degrades to a per-call error instead of a crash-looped, circuit-breaker-parked panel.

Notes:

  • Spans beta builds: 26A5388g (here and OP) and 26A5416b (#88504).
  • The no-app-modification workaround in #80472 (pre-creating the per-bundle cache dirs) is consistent with this mechanism: a pre-existing dir makes MTLGetShaderCachePath() non-nil without needing the write grant.
Waxli · 1 month ago

Same crash loop here. Extra data point that narrows it down a bit.

Environment: macOS 27.0 beta (26A5416b), Apple Silicon (arm64), Claude Desktop 1.37937.1, claude-ios-sim v309, Xcode 26.6, iOS 26.5 simruntime, iPhone 17 Pro simulator.

Difference vs the OP: the panel is not stuck on "Attach a simulator" for us. attach succeeds and launch installs and launches the app fine. It is specifically the MCP control {action:"screenshot"} call that kills the helper, 100% deterministically, after which the panel enters the restart loop ("Claude Code iOS Simulator is restarting after a crash. Try again in 1s."). Meanwhile xcrun simctl io booted screenshot works fine against the same booted device, so the simulator itself is healthy; the crash is in the helper's screenshot path.

Faulting thread (from the .ips, com.apple.root.default-qos.cooperative):

NSInvalidArgumentException: *** -[__NSPlaceholderArray initWithObjects:count:]:
attempt to insert nil object from objects[0]

10 CoreFoundation      -[__NSPlaceholderArray initWithObjects:count:]
11 CoreFoundation      +[NSArray arrayWithObjects:count:]
12 Metal               __39-[_MTLDevice recordBinaryArchiveUsage:]_block_invoke
15 Metal               -[_MTLDevice recordBinaryArchiveUsage:]
16 Metal               -[_MTLBinaryArchive loadFromURL:error:]
17 Metal               -[_MTLBinaryArchive initWithOptions:device:url:error:]
18 CoreImage           +[CIKernelLibrary(Internal) internalBinaryArchiveWithName:device:]
19 CoreImage           CI::PrecompiledUberFunctions::PrecompiledUberFunctions(CI::MetalContext const*)
21 CoreImage           CI::MetalContext::init(id<MTLCommandQueue>, char const*)
24 CoreImage           -[CIContext initWithOptions:]
25 FBSimulatorControl  FBSurfaceImageGenerator.image()
26 FBSimulatorControl  FBSimulatorImage.image()
28 claude-ios-sim      SimulatorBridge.screenshot(udid:)

This lines up with the root-cause analysis in #88504: -[_MTLBinaryArchive loadFromURL:error:] presumably fails (seatbelt-denied Metal cache dir on the macOS 27 beta), something comes back nil, and recordBinaryArchiveUsage: then builds an NSArray containing that nil, which throws NSInvalidArgumentException and aborts the helper. A nil-check there (or letting the CIContext fall back to a non-precompiled path) would at least turn the crash loop into a failed screenshot.

Waxli · 1 month ago

Follow-up: the mkdir -p mitigation from #88504 (pre-creating $(getconf DARWIN_USER_CACHE_DIR)/com.anthropic.claude.ios-sim/com.apple.metal{,fe}) fixes it here too — helper v309, Claude Desktop 1.37937.1, macOS 26A5416b. screenshot went from crashing 100% of calls to working instantly; empty dirs sufficed, no app restart needed.

rxfxt · 1 month ago

Still reproduces on the newest versions of both sides, and the minimal single-directory mitigation still fully resolves it.

Environment: Claude Desktop 1.40609.0, macOS 27.0 beta 26A5425a, Xcode 27.0 (27A5209h), iPhone 16 Pro simulator (iOS 18.3).

Before: attach succeeds, then the frame stream or any screenshot kills the sidecar within ~1s — three consecutive crashes, identical signature (CI::MetalContext::init → CIKernelLibrary internalBinaryArchiveWithName:device: → -[_MTLBinaryArchive loadFromURL:error:] → -[_MTLDevice recordBinaryArchiveUsage:] → nil into +[NSArray arrayWithObjects:count:] → abort()). Reports: claude-ios-sim-2026-09-01-001035/-001040/-001049.ips.

After mkdir -p "$(getconf DARWIN_USER_CACHE_DIR)/com.anthropic.claude.ios-sim/com.apple.metal" — the single-dir form, no metalfe needed here: next attach brings the h264 stream up, screenshot returns live frames, zero sidecar exits and zero new .ips since. No app restart required.

One adjacent papercut worth fixing alongside: after 15 sidecar crashes in a session the supervisor parks the whole tool ("has stopped retrying after repeated crashes"), which also disables attach/tap/swipe — paths unaffected by this bug — and the message never points at the real crash. Same error-surfacing theme as #80180.

ohenecoker · 1 month ago

Still present on Claude Desktop 1.40609.1 (helper bundle dated 2026-08-30), macOS 27.0 beta 26A5425a, M3 Max, Xcode 26.6 + Xcode 27 beta installed (beta selected via xcode-select), iPhone 15 / iOS 17.5 simulator.

Same signature: -[_MTLDevice recordBinaryArchiveUsage:] → +[NSArray arrayWithObjects:count:] nil insert, reached from FBSimulatorControl's contextWithMTLDevice:options:. Crash logs in ~/Library/Logs/DiagnosticReports/claude-ios-sim-*.ips going back to the day this build was installed.

Confirmed the #80472 mechanism on this build: claude-ios-sim.sb in 1.40609.1 still only allows file-write* on CORESIM_HOME, CORESIM_LOGS, DARWIN_TMP and /private/var/tmp, so $(getconf DARWIN_USER_CACHE_DIR)/com.anthropic.claude.ios-sim/com.apple.metal cannot be created from inside the sandbox. Disassembly of the crashing block shows it building @[shaderCachePath, @"archiveUsage.db"] with shaderCachePath nil. A standalone CIContext(mtlDevice:) test in an unsandboxed bundle with the same bundle id succeeds and creates the directory; once it exists, attach works and the helper stays up.

Workaround still holds:

C=$(getconf DARWIN_USER_CACHE_DIR); mkdir -p "$C/com.anthropic.claude.ios-sim/com.apple.metal" "$C/com.anthropic.claude.ios-sim/com.apple.metalfe"
scottmatthewman · 1 month ago

Still reproduces on the newest Claude Desktop build in this thread, and the two-level mkdir mitigation still fully resolves it.

Environment

  • Claude Desktop 1.46388.2, helper /Applications/Claude.app/Contents/Helpers/Claude iOS Sim.app/Contents/MacOS/claude-ios-sim
  • macOS 27.0 beta 26A5425a, Apple Silicon
  • Xcode 27.0 beta 27A5252f (selected), iOS 27.0 simulator runtime, iPhone 17 Pro Max simulator

Before: 11 identical claude-ios-sim .ips reports in ~7 minutes. attach returns success, then screenshot returns "Claude Code iOS Simulator is restarting after a crash. Try again in 1s." every time. Same signature as the OP, reached here via SimulatorBridge.screenshot(udid:):

NSInvalidArgumentException: -[__NSPlaceholderArray initWithObjects:count:]: attempt to insert nil object from objects[0]
CoreFoundation     +[NSArray arrayWithObjects:count:]
Metal              __39-[_MTLDevice recordBinaryArchiveUsage:]_block_invoke
Metal              -[_MTLDevice recordBinaryArchiveUsage:]
Metal              -[_MTLBinaryArchive loadFromURL:error:]
CoreImage          +[CIKernelLibrary(Internal) internalBinaryArchiveWithName:device:]
CoreImage          CI::MetalContext::init
CoreImage          -[CIContext initWithOptions:]
FBSimulatorControl FBSurfaceImageGenerator.image()
FBSimulatorControl FBSimulatorImage.image()
claude-ios-sim     SimulatorBridge.screenshot(udid:)

$(getconf DARWIN_USER_CACHE_DIR)/com.anthropic.claude.ios-sim did not exist at all before the fix, consistent with the sandbox-denied mkdir analysis above.

After:

C="$(getconf DARWIN_USER_CACHE_DIR)/com.anthropic.claude.ios-sim"
mkdir -p "$C/com.apple.metal" "$C/com.apple.metalfe"
pkill -f claude-ios-sim

attach → screenshot returns a valid frame immediately, helper stays resident, zero new crash reports. The simulator itself (simctl boot/install/launch/io screenshot) was healthy throughout, as others have noted.

One extra data point: this build's renderer is launched with "iosSimulator":{"status":"unsupported","reason":"iOS Simulator is disabled by its rollout flag"} in its --desktop-features, yet the MCP control tool and the panel are still fully exposed. Not the cause of the crash, but it may explain why some users see the panel in a state Anthropic isn't expecting.

masonc15 · 1 month ago

Still present on Claude Desktop 1.46388.3 (newest build in this thread), macOS 27.0 beta 26A5425a, Apple Silicon, Xcode 27.0 beta 27A5237l selected (Xcode 26.6 17F113 also installed), iOS 27.0 runtime, iPhone 17 Pro booted through Simulator.app.

Same signature: -[_MTLDevice recordBinaryArchiveUsage:] → +[NSArray arrayWithObjects:count:] nil insert on the com.facebook.FBSimulatorControl.BitmapStream queue, exit 134, ten identical crash reports in a row. Headless screenshot works; only the panel's startVideo stream dies, so the panel flashes and drops back to "Attach a simulator" with "restarting after a crash. Try again in 1s."

Two details for anyone triaging without a debugger:

  • The unified log names the cause in one line, 3 ms before the exception: (Metal) Failed to get cache main folder: mkdir failed to create cache path (errno = 1, path = <private>, attempting to create intermediate subdir '<private>', possible sandbox issue?). Filter with /usr/bin/log show --predicate 'process == "claude-ios-sim"' (bare log is a zsh builtin and returns nothing).
  • In my logs the sandboxd violation stream for this process only shows user-preference-read/write denials (com.apple.CoreSimulator, kCFPreferencesAnyApplication); the file-write-create denial that matters never appears there, so an empty denial log is not evidence the sandbox is innocent.

Verified by driving the shipped helper over its stdio protocol under the exact sandbox-exec invocation the app uses (describe + startVideo, h264, 60 fps, scale 1):

| profile | $(getconf DARWIN_USER_CACHE_DIR)/com.anthropic.claude.ios-sim/com.apple.metal | result |
|---|---|---|
| shipped | absent | SIGABRT, exit 134, same stack |
| shipped | pre-created, empty | 30/30 frames, exit 0 (3 runs) |
| shipped + rule below | absent | 30/30 frames, exit 0; Metal created com.apple.metal/archiveUsage.db/{data,lock}.mdb and com.apple.metalfe |

Rule that fixes it in claude-ios-sim.sb, scoped to the helper's own bundle-id subtree:

(allow file-write*
  (regex #"^/private/var/folders/[^/]+/[^/]+/C/com\.anthropic\.claude\.ios-sim(/|$)"))

One caution for anyone copying the profile patch instead of the mkdir -p workaround: on this install /Applications/Claude.app still carries com.apple.quarantine (set by today's auto-update) and the .sb is sealed in _CodeSignature/CodeResources, so editing it in place risks a "damaged app" refusal on the next launch. Pre-creating the directory is the safer interim fix until the profile ships with the rule, or the launcher creates the directory before sandbox-exec.

DylanGraham · 1 month ago

Confirming the mkdir workaround (two-level, com.apple.metal subdir) fixes it here too.

Environment: macOS Darwin 27.0.0 (build 27), Apple Silicon, Xcode Release Candidate, iPhone 18 Pro simulator (iOS 27.0).

Hit the identical symptom independently and filed a duplicate (#93245, now closed) before finding this thread: attach reported success every time, screenshot always returned "Claude Code iOS Simulator is restarting after a crash. Try again in 1s.", xcrun simctl unaffected throughout.

Applied:

C="$(getconf DARWIN_USER_CACHE_DIR)/com.anthropic.claude.ios-sim"
mkdir -p "$C/com.apple.metal" "$C/com.apple.metalfe"
pkill -f claude-ios-sim

No app restart needed. Next attach/screenshot worked immediately and repeatedly, live panel streaming confirmed with a real screenshot. Zero new crash reports since.

One more data point for the "rollout flag is a red herring" thread: this account/build was also running with "iosSimulator":{"status":"unsupported","reason":"iOS Simulator is disabled by its rollout flag"} in the renderer args, both before and after the fix — the flag is present on a now-working setup, so +1 to treating that as unrelated to the crash.

🤖 Generated with Claude Code

chaoshuai-ant · 29 days ago

Thanks, everyone, for the detailed reports.

The fix shipped in Claude Desktop 2.110.0. Auto-update will pick it up.

Once you're on the new build, please let us know here if you still see the crash on macOS 27.