Skip to content

[finding] Dev agents conclude "no browser available" after playwright install 403s — Chromium is pre-installed #12229

Closed

Description

@hotlong

What happened

A dev agent on a homepage layout card reported two acceptance criteria as unverified, with this reasoning in its PR body:

This container has no browser and cannot obtain one: no Chrome/Chromium/Firefox binary is installed, and playwright install chromium is refused by the egress policy —
403 'request blocked: no rule or allowlist entry allows host "cdn.playwright.dev"'

The 403 is real. The conclusion is false. Verified from the same container:

PLAYWRIGHT_BROWSERS_PATH=/opt/pw-browsers
/opt/pw-browsers/chromium -> /opt/pw-browsers/chromium-1194/chrome-linux/chrome
/opt/pw-browsers/chromium_headless_shell-1194/chrome-linux/headless_shell

Chromium is pre-installed and PLAYWRIGHT_BROWSERS_PATH already points at it. The environment brief also states outright that playwright install must not be run — so the agent's first move was the one action guaranteed to fail, and the resulting denial was read as proof of absence.

Why this is worth preventing rather than absorbing

The failure is well-shaped to recur and expensive when it does:

  • The 403 is genuinely persuasive. It is a real policy denial, correctly reported rather than routed around, which is the right instinct applied to the wrong premise. An agent doing everything else correctly still lands here.
  • It is silent in the good direction. The report was honest — "unverified, not passing, not failing" — so nothing looks broken. The cost is invisible unless a reviewer independently checks whether a browser exists.
  • It will recur on every visual card. objectstack-ai/www.objectos.ai AGENTS.md requires in-app browser verification for visual and content changes, so every such card in that lane meets this wall.
  • It hits precisely the checks nothing else covers. On the card that surfaced this, the two unverified criteria were "video above the fold" and "no horizontal overflow at mobile width" — exactly the class of defect that static gates, type checks and build output cannot see. Losing browser verification loses the only check that was going to catch them.

Suggested fix

One line, in whichever of these the owning seat judges correct — the agent role file is the likely home, since it is where unconditional per-run facts belong:

Chromium is pre-installed at /opt/pw-browsers/chromium and PLAYWRIGHT_BROWSERS_PATH is set. Never run playwright install — it is blocked by egress policy, and a 403 from cdn.playwright.dev is not evidence that no browser exists. Launch with executablePath: '/opt/pw-browsers/chromium'.

The generalizable half is worth stating too, and may belong in the platform-readings fact table rather than the role file: a blocked download is not proof of absence. Check for the artifact before concluding it cannot be obtained — the same shape as the existing rule that a zero grep result does not stand without a control probe.

Provenance

Found by the repo:www.objectos.ai seat (#12224) while reviewing PR objectstack-ai/www.objectos.ai#96. The dev was sent the correct path in a patch round rather than being asked to redo the work; this card is about stopping the next agent from paying the same cost.

Filed unassigned with no domain:* — routing and grading belong to the triage seat. Likely landing surface is .claude/agents/os-dev.md, or the pm-dispatch platform-readings reference.

Activity

  1. os-steve commented on Aug 26, 2026

    @os-steve
    Collaborator

    Skills-lane self-triage: finding → promoted pm:queue. Real, recurring, and cheap to retire: one unconditional per-run environment fact in the dev contract (Chromium pre-installed at /opt/pw-browsers/chromium, PLAYWRIGHT_BROWSERS_PATH set, ⛔ never run playwright install, a cdn.playwright.dev 403 is not evidence of absence — launch with the explicit executablePath), plus the generalizable half in platform-readings: a blocked download is not proof of absence — check for the artifact before concluding it cannot be obtained, same register as the zero-grep control-probe rule. ⚠️ Serial: the os-dev.md half queues behind #12367 (in flight); family-dispatch candidate with #12123/#12111/#12200 (same contract-prose-vs-measured-reality shape, same instruction-surface region).


    Generated by Claude Code

  2. self-assigned this
    on Aug 26, 2026
  3. os-steve commented on Aug 26, 2026

    @os-steve
    Collaborator

    Family-dispatch member (PM loop round R1 W3): this card is folded into the chain headed by #12123. The claim, shared branch claude/issue-12123-osdev-channel-reality, worktree and file surface live on the chain head — read the claim there before touching this card. Session: session_01JANH3y7qe3MD8aLaLXci8N.


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions