Skip to content

Unbounded waitForLoadState("domcontentloaded") in ensureOptimizedPageLoad can hang the agent #514

@lmorchard

Description

@lmorchard

Summary

PlaywrightBrowser.ensureOptimizedPageLoad() waits for the domcontentloaded load state with no timeout:

// packages/core/src/browser/playwrightBrowser.ts (ensureOptimizedPageLoad)
await this.page.waitForLoadState("domcontentloaded");

The subsequent waitForLoadState("load", { timeout: this.actionTimeoutMs }) and waitForTimeout(1000) are bounded, but the first domcontentloaded wait is not. If a navigation commits to a page (or SPA soft-navigation) that never fires DOMContentLoaded as Playwright tracks it, this await can block indefinitely — the same class of indefinite freeze fixed for frame.evaluate in #511.

Why it matters

ensureOptimizedPageLoad runs after every navigation (click-triggered nav, goto, back/forward). An unbounded wait here can freeze the whole agent with no error and no progress, just like the aria-tree frame hang.

Suggested fix

Give the domcontentloaded wait an explicit timeout (it's already wrapped in a try/catch that continues on failure, so a timeout would simply proceed to the bounded load wait). Reuse actionTimeoutMs or a dedicated constant.

Context

Discovered while diagnosing #511 (aria-tree frame.evaluate hang). Same root pattern: an unbounded Playwright wait against an adversarial page.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type
    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