Conversation
DevTools can accept connections shortly before Chromium opens its first tab, at startup and after a restart. firstPageTargetID looked up the page target once and failed immediately, so PATCH /display and the display step of /chromium/configure returned 500 "no page target found" in that window. Poll Target.getTargets for up to 5s before giving up, still honoring the caller's context.
yummybomb
marked this pull request as ready for review
October 5, 2026 18:53
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
PATCH /displayand thedisplaystep of/chromium/configurecan return 500no page target foundright after Chromium starts or restarts. DevTools can accept connections shortly before Chromium opens its first tab, andfirstPageTargetIDlooked up the page target once and failed on an empty result. In the server e2e suite this shows up as intermittent failures in whichever test resizes first, such asTestReplayRecordingIncludesAudioTrack,TestDisplayResolutionChange, orTestChromiumConfigureMultipartPowerset/display. Re-running the job usually passes.firstPageTargetIDnow pollsTarget.getTargetsevery 100ms for up to 5s, with the last sleep clamped to the deadline, before returningno page target found. It returns early with the context error if the caller's context is cancelled, and aTarget.getTargetserror still returns immediately. The lookup itself moves intofindPageTargetID.Callers:
SetDeviceMetricsOverrideandSetWindowBoundsMaximized(viaGetWindowBounds): the display handlers run these under a 10s timeout, so the wait fits inside it.DispatchStartURLAndWait:DispatchStartURLalready creates a tab if none exists, so the wait normally returns on the first poll.Tradeoff: when there really is no page target (for example, every tab was closed), the request now fails after about 5s instead of immediately. On the headless path with active recordings, the CDP viewport call is non-fatal, but recordings stay stopped until the handler returns, so the recording gap can grow by up to 5s in that case.
Testing
lib/cdpclient, with the wait timeout and poll interval made package vars so tests can adjust them:Target.getTargetscalls, and the resize succeeds on the fourth. Fails without the fix.no page target foundafter the (shortened) timeout. It runs under a context deadline so it fails instead of hanging if the wait is unbounded, and uses a long poll interval so it also covers the deadline clamp.context.Canceled.ctx.Done()case, the clamp, or the%wwrapping each fails at least one of these.go test -race ./lib/cdpclient/andgo test ./cmd/api/api/pass.TestSetDeviceMetricsOverridepassed 20 runs under-race, including on 1–2 CPUs with busy-loop processes competing.PATCH /displaywith a new size:500 failed to change resolution: CDP setDeviceMetricsOverride: no page target found(the same error CI hits)200500 ... no page target foundafter about 5.1s200, unchangedNote
Medium Risk
Changes timing and error behavior for display/configure CDP paths; legitimate no-tab cases now block up to 5s, which can extend recording gaps on headless flows.
Overview
Fixes intermittent
no page target foundfailures when display resize or Chromium configure runs right after DevTools connects but before the first tab exists.firstPageTargetIDno longer fails on the first emptyTarget.getTargetsresult. It polls every 100ms for up to 5s (package-level vars for tests), clamps the final sleep to the deadline, and still exits early on context cancellation. Lookup logic moves tofindPageTargetID, which returns""when no page target exists yet instead of an error.All callers that resolve the user-facing page window—
SetDeviceMetricsOverride,GetWindowBounds/SetWindowBoundsMaximized, andDispatchStartURLAndWait—inherit the wait. When no page target ever appears, operations fail after ~5s rather than immediately.Tests extend the fake CDP to simulate delayed page targets and add cases for bounded timeout, successful retry after empty polls, and context-cancelled waits.
Reviewed by Cursor Bugbot for commit dee70d1. Bugbot is set up for automated code reviews on this repo. Configure here.