Skip to content

fix(core): bound the domcontentloaded wait in ensureOptimizedPageLoad#517

Merged
lmorchard merged 1 commit into
mainfrom
fix/domcontentloaded-timeout
Jun 9, 2026
Merged

fix(core): bound the domcontentloaded wait in ensureOptimizedPageLoad#517
lmorchard merged 1 commit into
mainfrom
fix/domcontentloaded-timeout

Conversation

@lmorchard

Copy link
Copy Markdown
Collaborator

Closes #514.

Problem

PlaywrightBrowser.ensureOptimizedPageLoad() waited for domcontentloaded with no timeout:

await this.page.waitForLoadState("domcontentloaded");   // unbounded

The load wait immediately below is bounded by actionTimeoutMs, and the settle is a fixed 1s — only this first wait was unbounded. A navigation that commits to a page (or SPA soft-navigation) that never fires DOMContentLoaded as Playwright tracks it could hang the await indefinitely. Same class of freeze as #511, on the path that runs after every navigation (click-nav, goto, back/forward).

Fix

Pass { timeout: this.actionTimeoutMs } to the domcontentloaded wait, matching the load wait. It's already inside a try/catch that continues on failure, so a timeout simply proceeds to the bounded load wait and the settle delay — no behavior change on healthy pages, just removes the unbounded-hang risk. Reuses actionTimeoutMs rather than adding a new knob (both waits answer "how long to wait for the page to be ready").

Testing

  • New ensureOptimizedPageLoad test asserting waitForLoadState("domcontentloaded", { timeout: actionTimeoutMs }) is called (guards against the timeout being dropped again). Red before the fix, green after.
  • Full core suite: 862 pass (861 baseline + 1). Typecheck + prettier --check clean.

No live run: this is a latent path (needs a page that never fires DOMContentLoaded), not reliably reproducible on demand; the unit test is the meaningful guard and the change mirrors the already-bounded load wait.

Context

Follow-up to #511. Sibling reliability issues: #515 (stream timeout), #516 (agent-loop watchdog).

🤖 Generated with Claude Code

waitForLoadState("domcontentloaded") was called with no timeout, while the
"load" wait right below it is bounded by actionTimeoutMs. A navigation that
commits to a page (or SPA soft-navigation) that never fires DOMContentLoaded as
Playwright tracks it could hang this await indefinitely — the same class of
freeze fixed in #511, on the path that runs after every navigation.

Pass { timeout: this.actionTimeoutMs } to the domcontentloaded wait. It is
already wrapped in a try/catch that continues on failure, so a timeout simply
proceeds to the bounded "load" wait and the settle delay; no behavior change on
healthy pages.

Closes #514

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR prevents PlaywrightBrowser.ensureOptimizedPageLoad() from hanging indefinitely by bounding the waitForLoadState("domcontentloaded") call with the existing actionTimeoutMs, aligning it with the already-bounded "load" wait and preserving current behavior on healthy pages.

Changes:

  • Add { timeout: this.actionTimeoutMs } to page.waitForLoadState("domcontentloaded") inside ensureOptimizedPageLoad.
  • Add a unit test ensuring the domcontentloaded wait is invoked with the timeout (regression guard).

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
packages/core/src/browser/playwrightBrowser.ts Bounds the domcontentloaded load-state wait with actionTimeoutMs to avoid unbounded hangs.
packages/core/test/playwrightBrowser.test.ts Adds a regression test asserting the domcontentloaded wait includes the timeout.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@lmorchard lmorchard merged commit e00b625 into main Jun 9, 2026
14 checks passed
@lmorchard lmorchard deleted the fix/domcontentloaded-timeout branch June 10, 2026 00:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

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

2 participants