Skip to content

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

@dpearson2699

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

    No labels
    No labels
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions