openclaw - 💡(How to fix) Fix Browser tool: refs=aria snapshot broken — page._snapshotForAI removed in playwright-core 1.59.1 [1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#70158Fetched 2026-04-23 07:28:35
View on GitHub
Comments
0
Participants
1
Timeline
2
Reactions
0
Participants
Timeline (top)
labeled ×2

The browser tool's snapshot path calls page._snapshotForAI, which is not present in the shipped [email protected], so refs=aria snapshots and the generic AI snapshot path consistently fail with _snapshotForAI-related errors on openclaw 2026.4.15.

Error Message

Gateway logs (real samples; sensitive IDs trimmed; identical bundle code on 2026.4.14 and 2026.4.15):

2026-04-17T18:42:03.425+02:00 [tools] browser failed: {"error":"Error: refs=aria requires Playwright _snapshotForAI support."} raw_params={"action":"snapshot","target":"sandbox","targetId":"<id>","refs":"aria","snapshotFormat":"ai","depth":2,"maxChars":4000} 2026-04-18T08:53:41.600+02:00 [tools] browser failed: {"error":"Error: refs=aria requires Playwright _snapshotForAI support."} raw_params={"action":"snapshot","target":"sandbox","targetId":"<id>","refs":"aria","snapshotFormat":"ai","maxChars":12000}

Bundle code (dist/pw-ai-BJRFEth4.js):

// Generic AI snapshot path (line ~1063) const maybe = page; if (!maybe._snapshotForAI) throw new Error("Playwright _snapshotForAI is not available. Upgrade playwright-core."); let snapshot = (await maybe._snapshotForAI({ timeout: Math.max(500, Math.min(6e4, Math.floor(opts.timeoutMs ?? 5e3))), track: "response" }))?.full ?? "";

// refs=aria branch (line ~1108) if (opts.refsMode === "aria") { if (normalizeOptionalString(opts.selector) || normalizeOptionalString(opts.frameSelector)) throw new Error("refs=aria does not support selector/frame snapshots yet."); const maybe = page; if (!maybe._snapshotForAI) throw new Error("refs=aria requires Playwright _snapshotForAI support."); const built = buildRoleSnapshotFromAiSnapshot( (await maybe._snapshotForAI({ timeout: 5e3, track: "response" }))?.full ?? "", opts.options ); ... }

playwright-core/lib/client/page.js — the public replacement is present:

async ariaSnapshot(options = {}) { const result = await this.mainFrame()._channel.ariaSnapshot({ timeout: this._timeoutSettings.timeout(options), track: options._track, mode: options.mode, depth: options.depth }); return result.snapshot; }

Root Cause

The same root cause also breaks action: snapshot without refs when the request falls into the AI-snapshot path: Error: Playwright _snapshotForAI is not available. Upgrade playwright-core.

Fix Action

Fix / Workaround

Workaround: avoid refs: aria and AI-format snapshots; use refs: dom or the default snapshot (different code path that does not depend on _snapshotForAI).

Code Example

{"action":"snapshot","target":"sandbox","targetId":"<id>","refs":"aria","snapshotFormat":"ai","depth":2,"maxChars":4000}

---

# grep -c _snapshotForAI /app/node_modules/playwright-core/lib/client/page.js
0
# grep -c _snapshotForAI /app/dist/pw-ai-BJRFEth4.js
4

---

Gateway logs (real samples; sensitive IDs trimmed; identical bundle code on 2026.4.14 and 2026.4.15):


2026-04-17T18:42:03.425+02:00 [tools] browser failed: {"error":"Error: refs=aria requires Playwright _snapshotForAI support."} raw_params={"action":"snapshot","target":"sandbox","targetId":"<id>","refs":"aria","snapshotFormat":"ai","depth":2,"maxChars":4000}
2026-04-18T08:53:41.600+02:00 [tools] browser failed: {"error":"Error: refs=aria requires Playwright _snapshotForAI support."} raw_params={"action":"snapshot","target":"sandbox","targetId":"<id>","refs":"aria","snapshotFormat":"ai","maxChars":12000}


Bundle code (`dist/pw-ai-BJRFEth4.js`):


// Generic AI snapshot path (line ~1063)
const maybe = page;
if (!maybe._snapshotForAI) throw new Error("Playwright _snapshotForAI is not available. Upgrade playwright-core.");
let snapshot = (await maybe._snapshotForAI({
  timeout: Math.max(500, Math.min(6e4, Math.floor(opts.timeoutMs ?? 5e3))),
  track: "response"
}))?.full ?? "";

// refs=aria branch (line ~1108)
if (opts.refsMode === "aria") {
  if (normalizeOptionalString(opts.selector) || normalizeOptionalString(opts.frameSelector))
    throw new Error("refs=aria does not support selector/frame snapshots yet.");
  const maybe = page;
  if (!maybe._snapshotForAI) throw new Error("refs=aria requires Playwright _snapshotForAI support.");
  const built = buildRoleSnapshotFromAiSnapshot(
    (await maybe._snapshotForAI({ timeout: 5e3, track: "response" }))?.full ?? "",
    opts.options
  );
  ...
}


`playwright-core/lib/client/page.js` — the public replacement is present:


async ariaSnapshot(options = {}) {
  const result = await this.mainFrame()._channel.ariaSnapshot({
    timeout: this._timeoutSettings.timeout(options),
    track: options._track,
    mode: options.mode,
    depth: options.depth
  });
  return result.snapshot;
}

---

// refs=aria branch
-const maybe = page;
-if (!maybe._snapshotForAI) throw new Error("refs=aria requires Playwright _snapshotForAI support.");
-const built = buildRoleSnapshotFromAiSnapshot(
-  (await maybe._snapshotForAI({ timeout: 5e3, track: "response" }))?.full ?? "",
-  opts.options
-);
+const built = buildRoleSnapshotFromAiSnapshot(
+  (await page.ariaSnapshot({ mode: "ai", _track: "response", timeout: 5e3 })) ?? "",
+  opts.options
+);

 // generic AI snapshot branch
-const maybe = page;
-if (!maybe._snapshotForAI) throw new Error("Playwright _snapshotForAI is not available. Upgrade playwright-core.");
-let snapshot = (await maybe._snapshotForAI({
-  timeout: Math.max(500, Math.min(6e4, Math.floor(opts.timeoutMs ?? 5e3))),
-  track: "response"
-}))?.full ?? "";
+let snapshot = (await page.ariaSnapshot({
+  mode: "ai",
+  _track: "response",
+  timeout: Math.max(500, Math.min(6e4, Math.floor(opts.timeoutMs ?? 5e3)))
+})) ?? "";
RAW_BUFFERClick to expand / collapse

Bug type

Regression (worked before, now fails)

Beta release blocker

No

Summary

The browser tool's snapshot path calls page._snapshotForAI, which is not present in the shipped [email protected], so refs=aria snapshots and the generic AI snapshot path consistently fail with _snapshotForAI-related errors on openclaw 2026.4.15.

Steps to reproduce

  1. Run openclaw 2026.4.15 with the standard browser sandbox configuration.
  2. From an agent, call the browser tool with action: snapshot, refs: aria, e.g.:
{"action":"snapshot","target":"sandbox","targetId":"<id>","refs":"aria","snapshotFormat":"ai","depth":2,"maxChars":4000}
  1. Observe gateway log: [tools] browser failed: {"error":"Error: refs=aria requires Playwright _snapshotForAI support."}.

The same root cause also breaks action: snapshot without refs when the request falls into the AI-snapshot path: Error: Playwright _snapshotForAI is not available. Upgrade playwright-core.

Expected behavior

The browser snapshot returns an AI-formatted role-snapshot string — either via _snapshotForAI (if the bundle pinned a playwright-core version that exposes it) or via the public ariaSnapshot({mode: 'ai'}) replacement that the shipped playwright-core does expose.

Actual behavior

Both AI snapshot paths throw immediately:

  • refs=aria branch (dist/pw-ai-BJRFEth4.js line ~1109): refs=aria requires Playwright _snapshotForAI support.
  • generic AI snapshot branch (line ~1064): Playwright _snapshotForAI is not available. Upgrade playwright-core.

Direct verification inside the gateway container:

# grep -c _snapshotForAI /app/node_modules/playwright-core/lib/client/page.js
0
# grep -c _snapshotForAI /app/dist/pw-ai-BJRFEth4.js
4

The shipped playwright-core exposes ariaSnapshot({mode, _track, depth, ...}), which appears to be the public replacement for the removed _snapshotForAI.

OpenClaw version

2026.4.15 (also reproduced on 2026.4.14)

Operating system

AlmaLinux 9.4 (Linux 5.14.x x86_64), reproduced on two independent VPS

Install method

docker (image openclaw/openclaw:2026.4.15)

Model

n/a — bug is in the browser tool layer, independent of LLM

Provider / routing chain

n/a — browser tool, not an LLM request path

Additional provider/model setup details

No response

Logs, screenshots, and evidence

Gateway logs (real samples; sensitive IDs trimmed; identical bundle code on 2026.4.14 and 2026.4.15):


2026-04-17T18:42:03.425+02:00 [tools] browser failed: {"error":"Error: refs=aria requires Playwright _snapshotForAI support."} raw_params={"action":"snapshot","target":"sandbox","targetId":"<id>","refs":"aria","snapshotFormat":"ai","depth":2,"maxChars":4000}
2026-04-18T08:53:41.600+02:00 [tools] browser failed: {"error":"Error: refs=aria requires Playwright _snapshotForAI support."} raw_params={"action":"snapshot","target":"sandbox","targetId":"<id>","refs":"aria","snapshotFormat":"ai","maxChars":12000}


Bundle code (`dist/pw-ai-BJRFEth4.js`):


// Generic AI snapshot path (line ~1063)
const maybe = page;
if (!maybe._snapshotForAI) throw new Error("Playwright _snapshotForAI is not available. Upgrade playwright-core.");
let snapshot = (await maybe._snapshotForAI({
  timeout: Math.max(500, Math.min(6e4, Math.floor(opts.timeoutMs ?? 5e3))),
  track: "response"
}))?.full ?? "";

// refs=aria branch (line ~1108)
if (opts.refsMode === "aria") {
  if (normalizeOptionalString(opts.selector) || normalizeOptionalString(opts.frameSelector))
    throw new Error("refs=aria does not support selector/frame snapshots yet.");
  const maybe = page;
  if (!maybe._snapshotForAI) throw new Error("refs=aria requires Playwright _snapshotForAI support.");
  const built = buildRoleSnapshotFromAiSnapshot(
    (await maybe._snapshotForAI({ timeout: 5e3, track: "response" }))?.full ?? "",
    opts.options
  );
  ...
}


`playwright-core/lib/client/page.js` — the public replacement is present:


async ariaSnapshot(options = {}) {
  const result = await this.mainFrame()._channel.ariaSnapshot({
    timeout: this._timeoutSettings.timeout(options),
    track: options._track,
    mode: options.mode,
    depth: options.depth
  });
  return result.snapshot;
}

Impact and severity

  • Affected: every openclaw deployment using the browser tool's AI-format snapshot or refs=aria snapshot, on the shipped [email protected] (verified on 2026.4.14 and 2026.4.15).
  • Severity: Medium. The DOM snapshot path (refs=dom or default) goes through buildRoleSnapshotFromAriaSnapshot, doesn't depend on _snapshotForAI, and works fine. Only AI-format and refs=aria snapshots are unusable.
  • Frequency: Always — the bundle's call target does not exist regardless of input.
  • Consequence: Agents that try the AI-friendly aria snapshot fall back with errors and have to re-strategize, costing tokens and a turn. Side-mention only in #66809; no dedicated tracking issue prior.

Additional information

Suggested fix. Replace _snapshotForAI calls with ariaSnapshot({mode: 'ai', _track, ...}). Note the return-shape difference: _snapshotForAI returned {full: string}; ariaSnapshot returns string directly.

Conceptual diff:

 // refs=aria branch
-const maybe = page;
-if (!maybe._snapshotForAI) throw new Error("refs=aria requires Playwright _snapshotForAI support.");
-const built = buildRoleSnapshotFromAiSnapshot(
-  (await maybe._snapshotForAI({ timeout: 5e3, track: "response" }))?.full ?? "",
-  opts.options
-);
+const built = buildRoleSnapshotFromAiSnapshot(
+  (await page.ariaSnapshot({ mode: "ai", _track: "response", timeout: 5e3 })) ?? "",
+  opts.options
+);

 // generic AI snapshot branch
-const maybe = page;
-if (!maybe._snapshotForAI) throw new Error("Playwright _snapshotForAI is not available. Upgrade playwright-core.");
-let snapshot = (await maybe._snapshotForAI({
-  timeout: Math.max(500, Math.min(6e4, Math.floor(opts.timeoutMs ?? 5e3))),
-  track: "response"
-}))?.full ?? "";
+let snapshot = (await page.ariaSnapshot({
+  mode: "ai",
+  _track: "response",
+  timeout: Math.max(500, Math.min(6e4, Math.floor(opts.timeoutMs ?? 5e3)))
+})) ?? "";

Happy to send a PR if maintainers prefer.

Related:

  • #66809 — has a side-mention of the same error ("refs=aria requires _snapshotForAI ... likely a separate capability issue").
  • microsoft/playwright #36041, #36850, #36931, #37204 — confirm _snapshotForAI exists in current playwright but is unstable; upstream is converging on ariaSnapshot({mode: 'ai'}) as the public API.

Workaround: avoid refs: aria and AI-format snapshots; use refs: dom or the default snapshot (different code path that does not depend on _snapshotForAI).

extent analysis

TL;DR

Replace _snapshotForAI calls with ariaSnapshot({mode: 'ai', _track, ...}) to fix the issue.

Guidance

  • Identify all occurrences of _snapshotForAI in the code and replace them with ariaSnapshot({mode: 'ai', ...}).
  • Update the code to handle the return shape difference between _snapshotForAI and ariaSnapshot.
  • Test the updated code to ensure it works as expected.
  • Consider sending a PR with the changes if maintainers prefer.
  • As a temporary workaround, avoid using refs: aria and AI-format snapshots, and instead use refs: dom or the default snapshot.

Example

// refs=aria branch
- const built = buildRoleSnapshotFromAiSnapshot(
-   (await maybe._snapshotForAI({ timeout: 5e3, track: "response" }))?.full ?? "",
-   opts.options
- );
+ const built = buildRoleSnapshotFromAiSnapshot(
+   (await page.ariaSnapshot({ mode: "ai", _track: "response", timeout: 5e3 })) ?? "",
+   opts.options
+ );

// generic AI snapshot branch
- let snapshot = (await maybe._snapshotForAI({
-   timeout: Math.max(500, Math.min(6e4, Math.floor(opts.timeoutMs ?? 5e3))),
-   track: "response"
- }))?.full ?? "";
+ let snapshot = (await page.ariaSnapshot({
+   mode: "ai",
+   _track: "response",
+   timeout: Math.max(500, Math.min(6e4, Math.floor(opts.timeoutMs ?? 5e3)))
+ })) ?? "";

Notes

  • The suggested fix is based on the provided information and may not be exhaustive.
  • The return shape difference between _snapshotForAI and ariaSnapshot needs to be handled carefully to avoid errors.
  • The workaround may not be suitable for all use cases and should be used temporarily until the fix is implemented.

Recommendation

Apply the workaround by avoiding refs: aria and AI-format snapshots until the fix is implemented, as it is a safer and more temporary solution.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

FAQ

Expected behavior

The browser snapshot returns an AI-formatted role-snapshot string — either via _snapshotForAI (if the bundle pinned a playwright-core version that exposes it) or via the public ariaSnapshot({mode: 'ai'}) replacement that the shipped playwright-core does expose.

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

openclaw - 💡(How to fix) Fix Browser tool: refs=aria snapshot broken — page._snapshotForAI removed in playwright-core 1.59.1 [1 participants]