openai / openai/codex

Computer Use helper SIGTRAPs in UIElementTreeTransformation.transform: stale index passed to Array.remove(at:) (symbolicated)

Open
#43,573 6 comments 2 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug computer-use
Dominant language
Rust
Stars
125k
Forks
19.4k
PR merge metrics
PR metrics pending

Description

Summary

SkyComputerUseService traps with EXC_BREAKPOINT / SIGTRAP while building the accessibility tree for a macOS menu-bar app. The client only sees Sky Computer Use native pipe closed before response, because the helper dies mid-request. Attaching to the app is impossible; it fails 100% of the time.

The shipped helper binary retains local symbols, so the faulting frames can be resolved without a dSYM. The trap is a Swift index precondition in Swift.Array.remove(at:), called from ComputerUseCore.UIElementTreeTransformation.transform(item:context:rebuild:providerTitle:render:). Details and disassembly below.

This is very likely the same underlying defect behind the unsymbolicated SwiftUI accessibility-tree crashes in #34432, #32293, #28933, #32367 and #20683. Those reports all show EXC_BREAKPOINT / SIGTRAP on com.apple.root.user-initiated-qos.cooperative with AXNotificationObserver threads for the target pid, but none of them names the failing function.

Environment

  • macOS 26.6.2 (25G83), Apple Silicon
  • SkyComputerUseService 26.831.1000926 (build 1000926), bundle com.openai.sky.CUAService
  • slice_uuid 10a60435-199f-373b-b92d-2ec7971e1670
  • Installed at ~/.codex/computer-use/Codex Computer Use.app, selected via SKY_CUA_SERVICE_PATH
  • Plugin unified-computer-use 26.901.31953, launched from ChatGPT.app 26.901.31953
  • The installed helper is byte-identical (SHA-256 25e9141499b94c396f39afbdb7b19ed8f49e45dc8c61be61028ceab8f3807ce6) to the copy bundled at ChatGPT.app/Contents/Resources/cua_node/lib/node_modules/@oai/sky/Codex Computer Use.app, so this is the current helper, not a stale install.

Symbolicated faulting thread

libswiftCore  closure #1 in closure #1 in Swift._assertionFailure(_:_:file:line:flags:)
libswiftCore  Swift._assertionFailure(_:_:file:line:flags:)
libswiftCore  Swift.Array.remove(at: Swift.Int) -> A                          + 348
Sky           ComputerUseCore.UIElementTreeTransformation.transform(
                item:context:rebuild:providerTitle:render:)                   + 5464   (0x63f3f0)
Sky           <unnamed>                                                                (0x727ad0)
Sky           <unnamed>                                                                (0x637b28, 0x637898, 0x638990)
libswiftCore  Sequence.compactMap
Sky           ...                                                                      (0x637708, 0x637920, 0x638990)
libswiftCore  Sequence.compactMap
Sky           ...                                                                      (0x637708, 0x637920, 0x638990)
libswiftCore  Sequence.compactMap
Sky           ComputerUseCore.UIElementTree.transformed(using:in:apply:)               (0x637708)
Sky           ...                                                                      (0x226730, 0x2256f8, 0x227324, 0x22212c)
Sky           AccessibilitySupport.UIElementTreeTransaction.perform(work:)             (0x73a1f0)

Symbolication recipe, in case it is useful for triaging the other reports:

BIN="$HOME/.codex/computer-use/Codex Computer Use.app/Contents/MacOS/SkyComputerUseService"
nm -n -a "$BIN" | grep -E '^[0-9a-f]+ [tT] ' > /tmp/syms.txt
# for each frame: address = 0x100000000 + imageOffset, then take the nearest preceding symbol

The three nested compactMap frames put the failing parent node three levels below the root of the walk.

Analysis

Disassembling transform over 0x10063f0a00x10063f420 (stub targets resolved with dyld_info -fixups) shows this shape:

  1. Sequence.compactMap produces an [Int] of child indices.
  2. A loop walks those indices. Per index it calls Array.subscript.getter on the children array, Array._makeMutableAndUnique() on that same array, Array.append, and then either the render closure or the optional rebuild closure (cbz x23 selects between them). rebuild re-enters the recursive transform.
  3. After the loop, the index list is sorted with the comparator at 0x1006426fc, which is exactly { $0 > $1 } (descending), and each index is passed to Array.remove(at:) on that same children array.
  4. Array.remove(at:) trips its index precondition and the process traps.

Descending removal is the correct idiom, so the sort order is not the bug. The remaining explanation consistent with the code is that the index list is stale by the time it is replayed: the array is mutated during step 2, both directly (_makeMutableAndUnique plus append) and re-entrantly through render/rebuild. An index that was in range when it was collected can therefore be out of range when it is removed.

Two shapes of fix look plausible from the outside: re-validate against count inside the removal pass, or remove by element identity rather than by a snapshotted index. Either way, a defensive bound check here would turn a helper crash into a degraded subtree.

A related observation: an accessibility tree that mutates while it is being read is the natural trigger, and reading a closed NSMenu through accessibility asks the menu delegate to update it, which can add or remove items mid-walk. That would explain why this reproduces with no window on screen.

Reproduction

Target: Pinemeter, an open-source macOS SwiftUI menu-bar app. LSUIElement = true, NSStatusItem plus NSPopover, a SwiftUI Window scene, and a .commands block, so it still publishes an AXMenuBar.

  1. Launch the app. Do not open its popover or its Settings window.
  2. Attach Computer Use to bundle id ca.pineit.Pinemeter.
  3. The call fails with Sky Computer Use native pipe closed before response, and a fresh SkyComputerUseService-*.ips appears in ~/Library/Logs/DiagnosticReports/.

Observed 8 times across two days with an identical stack: twice on 2026-09-04 and six times on 2026-09-07. Each report carries AXNotificationObserver for pid <N> threads naming the target process. In the last run the app started at 12:14:10 and the helper crashed at 12:14:17, so no user interaction and no visible window are required.

I reproduced this on build 1.1.0-beta.32. The published release DMG is v1.0.16; it is the same app and the same structure, but I have not separately verified that tag.

Notes

  • Restarting the target app, restarting the helper, and opening the app's Settings window all fail identically.
  • There is no client-side way around it: cua.getApp(...) always emits accessibility state, so every attach path goes through the crashing transform.
  • disableDiff: true does not avoid it. #32293 reports the same crash with that flag set, and here the last crash hit a freshly restarted helper that had no previous tree to diff against.
  • The target app process is never affected. Only the helper dies.
  • The client surfaces a transport error with no indication that the helper crashed, which makes this expensive to diagnose. Surfacing "the Computer Use helper crashed" would help on its own, separately from the index fix.

Happy to supply full .ips reports or run further experiments against a test build.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the symbolicated UIElementTreeTransformation.transform frame in the shipped SkyComputerUseService binary and the supplied disassembly, then reproduce against Pinemeter using the listed Computer Use attach steps. Compare the child-index collection, render/rebuild callbacks, and descending removal pass. Done means the helper no longer traps when the accessibility tree mutates and the reported reproduction completes without the native pipe closing.

Written by the indexing model from the issue text.

Assessment

Tech stack
macos, swift
Domain
accessibility, desktop
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Needs clarification
Newbie friendliness
30/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.