anthropics / anthropics/claude-code

iOS Simulator panel: stream dies and never recovers on stable macOS 26.6 — detach() reports success but attach() still says "already attached"

Open
#94,360 1 comment 0 reactions 0 assignees View on GitHub
area:desktop bug has repro platform:macos
Dominant language
Python
Stars
145k
Forks
23.1k
PR merge metrics
PR metrics pending

Description

## Summary

On a **stable, non-beta macOS**, the desktop iOS Simulator panel's video stream dies and never comes back. `attach`, `tap`, `swipe` and `launch` keep working, so the panel looks connected and is driveable, but the pane shows 0 fps and every `screenshot` fails with `captureFailed`. `inspect` also reports itself unavailable.

The part I think is new, and the reason this is worth reopening: **`detach` reports success but does not actually clear the attached state, and the next `attach` short-circuits with "already attached" instead of renegotiating the stream.** That closes off the only in-tool recovery path. Quitting and reopening the Claude desktop app restores capture immediately.

This is the same failure signature as #81864, which was closed as stale. That report was on macOS 27 beta territory and noted detach/attach did not help; it did not identify *why*, or that an app restart is a reliable fix. #81520, #80472 and #93949 are the macOS 27 beta `BitmapStream` crash-loops and are a different bug — in my case the helper never crashes.

## Environment

| | |
|---|---|
| macOS | 26.6.2 (25G83) — **release, not a beta** |
| Claude desktop | 1.52386.6 |
| Claude Code | 2.1.270 |
| Xcode | 26.6 (17F113) |
| iOS runtime | 26.5 (23F77) |
| Device | iPhone 17 Pro |

## What distinguishes this from the known crash-loop bugs

The helper is healthy throughout:

```
$ pgrep -lf claude-ios-sim
20708 .../sandbox-exec -f .../claude-ios-sim.sb ... claude-ios-sim
20710 /Applications/Claude.app/Contents/Helpers/Claude iOS Sim.app/Contents/MacOS/claude-ios-sim

$ ls ~/Library/Logs/DiagnosticReports/ | grep -ic claude-ios-sim
0
```

No `SIGABRT`, no crash reports, no auto-restart. Only the encoder is dead.

## Reproduction

I hit this while driving a SwiftUI app through a long build session. The trigger appears to be changing device or app state out of band while the panel is attached:

1. Open the Claude desktop app with the simulator panel available.
2. From a shell, `xcrun simctl boot 'iPhone 17 Pro'` — i.e. boot the device *after* the panel helper is already running.
3. `attach` — succeeds.
4. `screenshot` — works at this point.
5. From a shell, `xcrun simctl terminate `, `xcrun simctl uninstall `, `xcrun simctl install `.
6. `screenshot` — now fails with `captureFailed`, and the pane reads 0 fps. Taps and swipes still land correctly.

Step 5 is the likely culprit: the stream looks bound per-boot/per-session, and nothing renegotiates it when the device state changes underneath.

## The recovery path is the actual bug

Verified in sequence, with nothing in between:

```
detach → "Detached iPhone 17 Pro 1 (8C3470B1-…)." ← reports success
attach → "Simulator panel already attached to iPhone 17 Pro 1 (8C3470B1-…)."
screenshot → "screenshot failed: captureFailed"
```

`detach` claims to have detached, and `attach` immediately afterwards believes it is still attached. Whatever `detach` tears down, it is not the state `attach` checks, so `attach` returns early and never rebuilds the encoder session. From the tool surface there is then no way back.

## Workaround

**Quit and reopen the Claude desktop app.** That respawns `claude-ios-sim` and capture works again on the first `attach` + `screenshot`, with no other change — same booted device, same installed app, same UDID. Confirmed in this session.

Two things that do *not* work: `detach` + `attach` (above), and having Simulator.app already open and rendering correctly — it was running and rendering fine the whole time the panel showed 0 fps.

`xcrun simctl io screenshot ` also keeps working throughout, which is a usable fallback for automated verification but does not help the human looking at the pane.

## Suggested fixes

1. Make `detach` actually clear the attachment state, so `attach` renegotiates rather than short-circuiting. Even without a root-cause fix for the encoder, this restores an in-tool recovery path.
2. Failing that, have `attach` verify the stream is live before reporting "already attached", and rebuild it if not.
3. Ideally, re-establish the stream automatically when the attached device's boot session or installed app changes, since driving a simulator from a shell alongside the panel is a normal thing to do during a build.

## Note on `inspect`

Throughout the same session, `inspect` returned `'inspect' is not available right now. Use 'screenshot' instead.` — including after the app restart, when `screenshot` was working again. That may be unrelated, or may be the same capability-gating; flagging it since #93949 mentions `inspect` unavailability alongside the capture failure.

Contributor guide

No contributing guide indexed for this repository

Research direction

Start by reproducing the simulator panel flow with attach, screenshot, detach, and attach after changing device state via xcrun simctl. Trace the attach/detach entry points and the stream state used by the panel; the fix is done when detach permits a subsequent attach to renegotiate capture and screenshot no longer returns captureFailed.

Written by the indexing model from the issue text.

Assessment

Tech stack
ios, macos
Domain
desktop-dev, mobile-dev
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
42/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.