Skip to content

Fix BiDi not initializing for RemoteWebDriver built via builder - #17792

Merged
pujagani merged 3 commits into
SeleniumHQ:trunkfrom
pujagani:pr-17778
Jul 17, 2026
Merged

Fix BiDi not initializing for RemoteWebDriver built via builder#17792
pujagani merged 3 commits into
SeleniumHQ:trunkfrom
pujagani:pr-17778

Conversation

@pujagani

@pujagani pujagani commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

🔗 Related Issues

Related to the PR-17778. Thank you @baflQA for helping fix this regression!

💥 What does this PR do?

Ensures that BiDi session is build when using the RemoteWebDriverBuilder

🤖 AI assistance

  • No substantial AI assistance used
  • AI assisted (complete below)
    • Tool(s):
    • What was generated:
    • I reviewed all AI output and can explain the change

🔄 Types of changes

  • Bug fix (backwards compatible)

@qodo-code-review

Copy link
Copy Markdown
Contributor

PR Summary by Qodo

Fix BiDi initialization when building RemoteWebDriver via builder

🐞 Bug fix 🧪 Tests 🕐 20-40 Minutes

Grey Divider

AI Description

• Initialize BiDi based on session response capabilities, not requested capabilities.
• Ensure RemoteWebDriver.builder() sessions attempt BiDi setup when webSocketUrl is returned.
• Add regression tests for BiDi requested/unsupported/not-requested scenarios.
Diagram

graph TD
  A["RemoteWebDriver.startSession"] --> B["NEW_SESSION command"] --> C["Returned capabilities"] --> D["createBiDi()"] --> E{"BiDi available?"}
  E -->|"yes"| F["BiDi connected"] --> H["getHandle() works"]
  E -->|"no"| G["Optional.empty"] --> I["BiDiException on getHandle()"]
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Lazy-init BiDi on first getHandle() call
  • ➕ Avoids opening a WebSocket during session creation when BiDi is never used
  • ➕ Eliminates any startup-time BiDi connection failures/log warnings unless BiDi is actually accessed
  • ➖ Shifts failures later (first use instead of session start), which may surprise users
  • ➖ Requires additional synchronization/state handling to avoid repeated init attempts
2. Track an explicit 'BiDi requested' flag and gate initialization
  • ➕ Avoids attempting BiDi init if the user did not request it, even if server returns a webSocketUrl
  • ➕ Keeps log messaging ('BiDi was requested but...') strictly accurate
  • ➖ Adds state/branching and needs careful handling across constructors/builders and subclasses
  • ➖ Does not address the core bug unless still tied to response capabilities

Recommendation: Current approach (initialize from the session response capabilities) is the right minimal fix for builder-created RemoteWebDriver sessions because it keys off the authoritative server-returned webSocketUrl. Consider lazy-init only if WebSocket startup cost or early-connection side effects become an issue in practice.

Files changed (3) +100 / -3

Bug fix (1) +1 / -3
RemoteWebDriver.javaAlways attempt BiDi initialization after session creation +1/-3

Always attempt BiDi initialization after session creation

• RemoteWebDriver.startSession now unconditionally calls createBiDi() after setting returned capabilities and sessionId. BiDi initialization is therefore driven by the server-returned webSocketUrl capability (createBiDi() still no-ops when webSocketUrl is missing or not a String).

java/src/org/openqa/selenium/remote/RemoteWebDriver.java

Tests (2) +99 / -0
RemoteWebDriverBuilderTest.javaAdd builder regression tests for BiDi initialization and unsupported servers +92/-0

Add builder regression tests for BiDi initialization and unsupported servers

• Adds tests ensuring BiDi initialization is attempted for builder-created drivers when the session response includes a webSocketUrl string (validated via expected warning log). Adds a test that when the server echoes webSocketUrl=true (unsupported), BiDi remains unavailable and getHandle throws BiDiException.

java/test/org/openqa/selenium/remote/RemoteWebDriverBuilderTest.java

RemoteWebDriverUnitTest.javaAdd unit test to ensure BiDi is not available when not requested +7/-0

Add unit test to ensure BiDi is not available when not requested

• Adds a unit test asserting that a driver created without requesting BiDi throws BiDiException when getHandle is accessed, protecting the non-BiDi default behavior.

java/test/org/openqa/selenium/remote/RemoteWebDriverUnitTest.java

@qodo-code-review

Copy link
Copy Markdown
Contributor

Code Review by Qodo

🐞 Bugs (2) 📘 Rule violations (0) 📎 Requirement gaps (0) 📜 Skill insights (0)

Context used
✅ Compliance rules (platform): 18 rules

Grey Divider


Action required

1. BiDi drops builder auth 🐞 Bug ≡ Correctness
Description
RemoteWebDriverBuilder creates the HTTP session using a derived ClientConfig that includes
baseUri/credentials, but still constructs RemoteWebDriver with the original clientConfig; after this
PR, BiDi initialization uses RemoteWebDriver.clientConfig, so the BiDi WebSocket can be opened
without the builder’s credentials/auth settings. This can make BiDi unusable against authenticated
remotes even though session creation succeeded.
Code

java/src/org/openqa/selenium/remote/RemoteWebDriver.java[295]

+      this.biDi = createBiDi();
Evidence
The builder uses a credential-bearing derived config to create the HTTP client, but passes the
original config into RemoteWebDriver. Since createBiDi uses RemoteWebDriver.clientConfig to build
the WebSocket client, credentials won’t be applied; JdkHttpClient shows credentials are required to
set up authentication for connections including WebSockets.

java/src/org/openqa/selenium/remote/RemoteWebDriverBuilder.java[400-431]
java/src/org/openqa/selenium/remote/RemoteWebDriver.java[456-462]
java/src/org/openqa/selenium/remote/http/jdk/JdkHttpClient.java[112-131]
java/src/org/openqa/selenium/bidi/Connection.java[80-86]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`RemoteWebDriverBuilder` computes `driverClientConfig` (baseUri + credentials) for the HTTP client used in the handshake/session. But it instantiates `RemoteWebDriver` with the unmodified `clientConfig`. With this PR, `RemoteWebDriver.startSession` now calls `createBiDi()`, which uses `this.clientConfig` to create the WebSocket client; therefore the WebSocket may be created without credentials/authentication.

### Issue Context
`JdkHttpClient` only configures an authenticator when `ClientConfig.credentials()` (or baseUri userInfo) is present; losing credentials will cause the WebSocket upgrade/auth to fail.

### Fix Focus Areas
- Ensure the `RemoteWebDriver` instance receives the *effective* config used to create the session (`driverClientConfig`), or otherwise ensure credentials/auth settings are available to `createBiDi()`.
- Add/adjust tests for builder + authenticateAs + BiDi to prevent regressions.

### Fix Focus Areas (files/lines)
- java/src/org/openqa/selenium/remote/RemoteWebDriverBuilder.java[397-431]
- java/src/org/openqa/selenium/remote/RemoteWebDriver.java[435-469]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

2. BiDi ignores opt-in flag 🐞 Bug ☼ Reliability
Description
RemoteWebDriver.startSession now always invokes createBiDi(), so any remote that returns a string
webSocketUrl will cause an immediate WebSocket connection attempt even when the client didn’t
request BiDi via 'webSocketUrl: true'. This can add unexpected overhead and warnings/failures for
sessions that did not opt in.
Code

java/src/org/openqa/selenium/remote/RemoteWebDriver.java[295]

+      this.biDi = createBiDi();
Evidence
The PR change makes BiDi initialization unconditional, and createBiDi() will open a WebSocket
whenever the returned capability is a string. Other code treats webSocketUrl as an opt-in
capability, so removing the guard changes behavior for remotes that return the URL without an
explicit request.

java/src/org/openqa/selenium/remote/RemoteWebDriver.java[263-296]
java/src/org/openqa/selenium/remote/RemoteWebDriver.java[435-469]
java/src/org/openqa/selenium/bidi/Connection.java[80-86]
java/src/org/openqa/selenium/grid/node/local/LocalNode.java[1242-1250]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`RemoteWebDriver.startSession` now always calls `createBiDi()`, which opens a WebSocket immediately when the server returns a string `webSocketUrl`. This removes the previous client-side opt-in gate (`webSocketUrl: true`) and can cause unrequested BiDi connections.

### Issue Context
- `createBiDi()` establishes a WebSocket immediately via `new Connection(...)`.
- Grid code/comments treat absence of `webSocketUrl` as “user did not set it”, i.e., opt-in.

### Fix Focus Areas
- Reintroduce an explicit “BiDi requested” boolean gate before calling `createBiDi()`.
- Ensure the builder path passes/records whether the client requested BiDi (so the guard still allows the builder scenario).

### Fix Focus Areas (files/lines)
- java/src/org/openqa/selenium/remote/RemoteWebDriver.java[263-296]
- java/src/org/openqa/selenium/remote/RemoteWebDriverBuilder.java[397-431]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Qodo Logo

Comment thread java/src/org/openqa/selenium/remote/RemoteWebDriver.java
Comment thread java/src/org/openqa/selenium/remote/RemoteWebDriver.java
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

C-java Java Bindings

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants