Skip to content

[Bug]: ui-automation element refs become unavailable after debugger-paused tap #445

Description

@dpearson2699

Bug Description

When a ui-automation tap --element-ref action triggers an LLDB breakpoint and pauses the app, the runtime UI automation snapshot cache appears to be dropped. After continuing the app, a follow-up tap against a same-screen element ref immediately fails with No runtime UI snapshot is available for this simulator.

This blocks debugger-assisted reproduction workflows that need to issue rapid repeated interactions through element refs, such as opening and closing the same SwiftUI disclosure/card view quickly to reproduce an animation bug. A coordinate fallback can work for reproduction, but it bypasses the normal runtime snapshot/element-ref workflow.

If invalidating refs after a debugger pause is intentional, the current behavior still seems worth improving because the failure differs from the normal stale-ref path and does not explain that the snapshot was invalidated or that a fresh snapshot-ui/wait-for-ui is required.

Debug Output

Command:

xcodebuildmcp doctor doctor --output json --style minimal

Output:

{
  "schema": "xcodebuildmcp.output.doctor-report",
  "schemaVersion": "2",
  "didError": false,
  "error": null,
  "data": {
    "serverVersion": "2.6.2",
    "checks": [
      {
        "name": "xcode",
        "status": "ok",
        "message": "Xcode 26.5 - Build version 17F42 (/Applications/Xcode.app/Contents/Developer)"
      },
      {
        "name": "process-tree",
        "status": "ok",
        "message": "Running under Xcode: No; 4 process entries"
      },
      {
        "name": "axe",
        "status": "ok",
        "message": "Available: Yes; UI automation: Yes; Video capture: Yes"
      },
      {
        "name": "xcodemake",
        "status": "ok",
        "message": "Enabled: No; Binary: No; Makefile: Not checked"
      },
      {
        "name": "mise",
        "status": "warning",
        "message": "Running under mise: No; Available: No"
      },
      {
        "name": "debugger-dap",
        "status": "ok",
        "message": "Selected backend: lldb-cli; lldb-dap available: Yes"
      },
      {
        "name": "manifest-tools",
        "status": "ok",
        "message": "Total tools: 82; Workflows: 15"
      },
      {
        "name": "runtime-registration",
        "status": "warning",
        "message": "Runtime registry unavailable."
      },
      {
        "name": "xcode-ide-bridge",
        "status": "ok",
        "message": "Workflow enabled: No; Connected: No; Proxied tools: 0"
      },
      {
        "name": "sentry",
        "status": "ok",
        "message": "Enabled: Yes"
      }
    ]
  }
}

Editor/Client

Codex desktop app, driving XcodeBuildMCP primarily through the CLI for this reproduction.

MCP Server Version

2.6.2

LLM

GPT-5 Codex

MCP Configuration

N/A for the minimal repro path above. The issue was observed using the installed CLI at /opt/homebrew/bin/xcodebuildmcp.

Steps to Reproduce

  1. Launch an iOS simulator app and capture a runtime UI snapshot with verbose element refs:

    xcodebuildmcp ui-automation snapshot-ui \
      --simulator-id <UDID> \
      --output json \
      --style minimal \
      --verbose
  2. Pick a tappable same-screen elementRef from the snapshot output, for example a SwiftUI disclosure/card view ref such as e99.

  3. Attach LLDB to the simulator app and set a breakpoint that will be hit by that tap action.

  4. Tap the element ref:

    xcodebuildmcp ui-automation tap \
      --simulator-id <UDID> \
      --element-ref e99 \
      --post-delay 0 \
      --output json \
      --style minimal

    The tap succeeds and the app stops at the LLDB breakpoint.

  5. Continue the app from LLDB.

  6. Immediately try to issue a second tap against the same visible element/ref, or another same-screen ref from the same snapshot:

    xcodebuildmcp ui-automation tap \
      --simulator-id <UDID> \
      --element-ref e99 \
      --pre-delay 0.05 \
      --post-delay 0 \
      --output json \
      --style minimal

Expected Behavior

One of these would be expected:

  • same-screen refs remain usable after continuing from the debugger pause;
  • the cached snapshot remains present and fails through the normal stale/expired-ref path if it is no longer valid;
  • the error clearly explains that the debugger pause/app state transition invalidated the runtime snapshot and that the caller must refresh with snapshot-ui/wait-for-ui;
  • or there is a supported way to keep/restore refs for debugger-assisted rapid interaction workflows.

Actual Behavior

The second ref-based tap fails immediately because the simulator no longer has a runtime UI snapshot available. This happens even though the ref came from a recent snapshot and the app remains on the same visible screen after continuing from the breakpoint.

This is different from the normal stale-ref behavior. In the same debugging session, an older ref produced an expiration-style error, while the post-breakpoint follow-up produced a no-snapshot error.

Error Messages

No runtime UI snapshot is available for this simulator.

A related stale-ref path observed separately in the same session produced:

The runtime UI snapshot for this simulator has expired.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions