iOS Simulator panel helper (claude-ios-sim) keeps encoding forever after the simulator is shut down — unbounded VTEncoderXPCService growth, only a manual kill stops it
Summary
The desktop iOS Simulator panel helper, claude-ios-sim, keeps running H.264 encoding after its simulator has been shut down and after the session that used it is gone. It opens new VCPRateControlSessions forever at full stream resolution and bitrate with zero frames flowing, and each one feeds a VTEncoderXPCService whose memory is never released.
Nothing in the product ever ends this. The helper is owned by the app, not by a session, so /clear, ending the session, and shutting down the simulator all leave it running. The only cure I have found is killing it by hand in Activity Monitor — which I have now had to do repeatedly, across several projects, over weeks.
This is measurement, not inference: I traced the encoder's client from the XPC peer name in the unified log.
Evidence
Captured on 15 September 2026, with no simulator device booted at all (xcrun simctl list devices booted was empty) and no Simulator.app running.
The encoder's client, straight from the log — the peer PID is the helper:
VTEncoderXPCService[57227]: [com.apple.xpc:connection] activating connection:
name=com.apple.coremedia.videoencoder.peer[55705].0x12b9041c0
$ ps -p 55705 -o pid,etime,command
PID ELAPSED COMMAND
55705 02:26:32 /Applications/Claude.app/Contents/Helpers/Claude iOS Sim.app/Contents/MacOS/claude-ios-sim
Still emitting, live, 2h 26m after the device went away:
16:51:19 claude-ios-sim[55705] (VideoProcessing) VCPRateControlSession (0x84017e7698) (1206x2622):
input_fps=0.00, enc_fps=0.00, tx_fps=0.00, idr_fps=0.00, refresh_fps=0.00,
baselayer_fraction=-1.0, bit_rate (video/target)=-1/-1, 0/12000000, enc_time=0.00 ms
Note input_fps=0.00 with a 12 Mbps target at 1206x2622. It is encoding nothing, at full cost, indefinitely.
Volume over a 150-minute window, from log show --predicate 'processIdentifier == 55705':
| Measure | Value |
|---|---|
| Distinct VCPRateControlSession objects | 63 |
| Rate-control log lines | 169,784 |
| Helper uptime when measured | 2h 27m |
| VTEncoderXPCService RSS at that moment | 163 MB |
| Helper phys_footprint | 188 MB |
Also left behind with no booted device: SimStreamProcessorService and SimAudioProcessorService, both alive 2h 32m.
The encoder is a child of the helper's lifetime, not an independent leak — killing the helper took its 163 MB encoder with it immediately:
$ pkill -f claude-ios-sim
# VTEncoderXPCService[57227] gone in the same instant
Activity Monitor has shown VTEncoderXPCService above 4 GB on this machine on earlier occasions, which is what sent me looking. I did not re-observe 4 GB during this capture — the figures in the table are what I measured this time — but 63 accumulating encoder sessions over 2.5 hours is a plausible path to it, and the growth is unbounded because nothing ever ends the loop.
Steps to reproduce
- Attach the iOS Simulator panel to a booted simulator and use it normally.
- Shut the simulator down, and end or
/clearthe Claude Code session. - Quit nothing — leave the Claude desktop app open, as you would between tasks.
pgrep -fl claude-ios-sim— still running, hours later.log show --last 30m --predicate 'process == "claude-ios-sim"' | grep VCPRateControlSession— still creating encoder sessions atinput_fps=0.00.- Watch
VTEncoderXPCServicein Activity Monitor grow.
Expected
With no booted device and no attached panel, the helper should tear down its encoder sessions and idle at zero cost — or exit, and be respawned on the next attach. It should certainly never create new encoder sessions for a device that no longer exists.
Actual
It creates new rate-control sessions indefinitely at full resolution and bitrate, encoding no frames, and only a manual kill stops it.
Possibly the same root cause as #94360
#94360 reports that detach returns success without actually clearing the attached state. If detach never tears the stream down, that would explain exactly this: the encode loop is never told to stop, so it keeps spinning on a device that has gone. The two may be one bug seen from either end — that one from the tool's side, this one from the process table's.
Environment
| | |
|---|---|
| macOS | 26.7 (25G229) — release, not a beta |
| Hardware | Apple M1 Pro, 16 GB |
| Claude desktop | 1.52386.6 |
| Claude Code | 2.1.272 |
| Xcode | 26.6 (17F113) |
The helper never crashed here, so this is not the macOS 27 beta Metal/CoreImage crash-loop family (#90684, #92442, #93580).
Workaround, for anyone else hitting it
pkill -f claude-ios-sim — the app starts a fresh helper the next time a panel opens. I have since automated it on a guard that refuses to fire while any simulator device is booted, so a sweep can never disturb live work.
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗