Blolabel
← Notes
event 7 min read

WebDriverAgent 16.14.1 stops sending its idle check to WebKit; phoneshell had the check on for 189 web runs and its grader still read the page in 29 of 30

The bug needs two things: the deadline turned on, and a snapshot request aimed at an element that lives in WebKit's process. phoneshell has the first. Its published runs suggest it does not make the second, and its code says why.

WebDriverAgent 16.14.1, released on 7 October 2026, stops sending its accessibility idle check to WebKit's content process, which the check had been crashing, leaving web pages blank. phoneshell has run the affected code since 8 September: WebDriverAgent 16.12.4 with accessibilityDeadline set to 10 seconds. In the 189 web-content runs it has published since that setting, the grader found "Example Domain" in the accessibility tree 29 times out of 30. With no screenshot sent at all, the text probes passed 30 of 30.

Abstract technical illustration of two parallel signal paths, one ending in a broken node and one passing through to a lit node

What changed on 7 October

The setting arrived in WebDriverAgent 16.8.0 on 24 August 2026 (PR #1214). It is off by default. When it is above zero, a swizzle on requestSnapshotForElement first asks the target app, through the private notifyWhenEventLoopIsIdleForApplication: call, whether its run loop is alive, and aborts the snapshot if no answer comes inside the deadline. The point was to stop one hung app from blocking the whole server (issue #1210).

The target app is resolved from the element's own process id. On 5 October, GitHub user bddsko reported (issue #1290) that elements inside a WKWebView are remote accessibility elements owned by com.apple.WebKit.WebContent, so the idle-check action went there. WebContent does not implement it, throws an unrecognized-selector exception and aborts about 1.5 seconds into the page load. WebKit reloads once, crashes again, and gives up; every lookup on the page then times out. The report used Appium 3.8.0, xcuitest driver 12.13.3, WebDriverAgent 16.12.11 and an iOS 18.3.1 simulator with the deadline at 30.

The fix (PR #1293, shipped in 16.14.1 at 03:49 UTC) adds eight lines: when the resolved process's bundle id starts with com.apple.WebKit., call the original snapshot and skip the check. Its author validated it on an iPhone 17 simulator on iOS 27.0, with a negative control that returns a nil snapshot without the fix, and says the original iOS 18.3.1 crash environment was not available. No physical device was tested. The same release also fixes screen geometry on the selected display (#1291), and xcuitest driver 12.15.1 and 12.15.2 followed the same day.

accessibilityDeadline, from setting to fix 24 AugWDA 16.8.0adds the setting (#1214) 6 SepWDA 16.12.4phoneshell's pinned tag 8 Sep 04:53 UTCphoneshell sets 10.0 (f0c538d) 8 to 9 Sep189 web runs 5 Octissue #1290WebContent crash 7 OctWDA 16.14.1fix (#1293) Sources: GitHub releases of appium/WebDriverAgent; phoneshell git history (config.py); published result timestamps. Axis not to scale.

phoneshell's web runs with the check switched on

phoneshell pins WebDriverAgent at v16.12.4 (WDA_TAG in device.py), and the vendored copy carries the swizzle exactly as the issue describes it. Its session settings in config.py set accessibilityDeadline: 10.0, added in commit f0c538d at 04:53 UTC on 8 September. Every cross-model run published on the Hugging Face dataset came after that. We counted the web-content tasks in those files: the Safari tasks, the twenty probe pages on blolabel.ai, and resilience.deep_start, which ends on example.com.

What had to come out of a web pageRunsPassedWhat the failures wereSource
Grader finds "Example Domain" in the tree30291: resilience.deep_start, Claude Opus 4.8, 4 turns, cause not recordedxv, xv2, v4, xv-text, xv-novision
Grader matches "iso 8601" on screen77nonesame
Text probe, no screenshot sent3030noneexp2-n
Text probe, screenshot sent30291: Safari not in frontexp2-v and others
Picture probe, screenshot sent3030noneexp2-v
Picture probe, no screenshot sent30030: the word exists only as pixels, by designexp2-n
All web-content runs18915530 pixel-only answers, 3 Safari not in front, 1 heading not foundour count

A blank page would show up in three places at once: the "Example Domain" checks, which are a WebDriverAgent tree read by the grader itself rather than anything the model says; the text probes run without a screenshot, where the tree is the only channel the model has; and the turn counts. The first two came back at 29 of 30 and 30 of 30. The one heading miss is a run that started three levels deep in Settings, and nothing in the row says whether the page was blank or never loaded. One run, so treat it as unexplained rather than as a sighting of the bug.

Web-content runs after accessibilityDeadline was set to 10 s, by what had to be read passed failed 0 8 16 24 32 runs 29 1 Example Domain 7 0 iso 8601 30 0 text, no image 29 1 text, image 30 0 picture, image 0 30 picture, no image First two bars are grader checks; the rest are probe answers. Source: phoneshell-bench results/*.jsonl after 2026-09-08T04:53:29Z.

Why the check never reached WebKit here

The crash needs a snapshot request aimed at an element whose process is WebContent. phoneshell perceives the screen with one GET /source per observation, which snapshots the application root: the process id is MobileSafari's, Safari answers the idle check, and the web subtree comes back inside that one snapshot. Taps go to /wda/tap as coordinates. The only element lookups in the action layer (actions.py, around line 974) find a text field to type into, and in these tasks that field is Safari's own address bar. That is our reading of the code, not a trace from the phone, which has been parked under runtime/automation-off since 17 September.

Where WebDriverAgent 16.8.0 to 16.14.0 sends the idle check, by request shape Element lookup inside a web view (issue #1290) find / attribute ona web element pid = element's processcom.apple.WebKit.WebContent idle-check AX actionsent to WebContent unrecognized selectorSIGABRT at ~1.5 s →→→ WebKit reloads the page once, the process crashes again, WebKit gives up: blank page, every lookup times out. 16.14.1 (#1293): if the bundle id starts with com.apple.WebKit., skip the idle check and use the original snapshot. Reported on an iOS 18.3.1 simulator with WDA 16.12.11 and accessibilityDeadline 30. Fix validated on an iOS 27.0 simulator only. phoneshell on 16.12.4 with accessibilityDeadline 10.0 GET /sourceonce per observation pid = Safari app rootcom.apple.mobilesafari idle check answeredby Safari's run loop web subtree returnedin the same snapshot →→→ Taps: POST /wda/tap at element centre coordinates. Element lookups only to find a text field to type into. Result in the published runs: the grader read "Example Domain" from the tree in 29 of 30 checks. Our reading of client.py and actions.py, not a device trace. The phone has been under runtime/automation-off since 17 September. Sources: appium/WebDriverAgent issue #1290, PR #1293, XCAXClient_iOS+FBSnapshotReqParams.m at v16.12.4; phoneshell wda/client.py, actions.py.

The rows also say less than we would like about the hardware. The xv2 rows record an iPhone 14 Pro on iOS 26.3.1. The other files record no device. The issue was an iOS 18.3.1 simulator, the fix was tested on an iOS 27.0 simulator, and nobody in the thread reports a physical phone. So the evidence is two-sided and partial: the bug is real on a simulator, absent from 189 iOS 26 hardware runs that never made the triggering request.

What it means if you run WebDriverAgent with a deadline

Check it yourself

# the fix and the code it changes
gh api repos/appium/WebDriverAgent/pulls/1293/files --jq '.[0].patch'
curl -s https://raw.githubusercontent.com/appium/WebDriverAgent/v16.12.4/WebDriverAgentLib/Categories/XCAXClient_iOS+FBSnapshotReqParams.m | grep -n "processIdentifier\|notifyWhenEventLoopIsIdle"

# phoneshell's settings and pin
grep -n "accessibilityDeadline" phoneshell/config.py
grep -n "WDA_TAG" phoneshell/device.py
grep -n "def source\|/wda/tap" phoneshell/wda/client.py

# the published runs
for f in exp2-n exp2-v v4 xv-novision xv-text xv xv2; do
  curl -sLO https://huggingface.co/datasets/blolabel/phoneshell-bench/resolve/main/results/$f.jsonl; done
# keep rows with started_at >= 1788843209 (2026-09-08T04:53:29Z) and task_id starting
# safari., probe., or equal to resilience.deep_start; group failures by the first failing check

What would prove this wrong

By 31 December 2026 we will run the six Safari tasks twice on an iOS 26 iPhone, once on 16.12.4 and once on 16.14.1, both with the deadline at 10 seconds, adding one element lookup on the example.com link before each tap. Our prediction: on 16.12.4 the lookup blanks the page in at least half the runs, and on 16.14.1 in none. If 16.12.4 survives the lookups as well, the crash is specific to the simulator or to iOS 18, and the fix matters less on current hardware than the issue suggests. If /source alone ever produces a blank page on 16.12.4, our explanation of why phoneshell escaped is wrong.

Sources