Skip to content

[java][bidi] Clear fetchError listener in Network.close() - #17903

Open
Mochxd wants to merge 1 commit into
SeleniumHQ:trunkfrom
Mochxd:fix-bidi-network-close-fetch-error
Open

[java][bidi] Clear fetchError listener in Network.close()#17903
Mochxd wants to merge 1 commit into
SeleniumHQ:trunkfrom
Mochxd:fix-bidi-network-close-fetch-error

Conversation

@Mochxd

@Mochxd Mochxd commented Aug 11, 2026

Copy link
Copy Markdown

🔗 Related Issues

None. I noticed this while reading through the BiDi Network module.

💥 What does this PR do?

onFetchError() subscribes to network.fetchError, but close() never cleared it. The other four network events all get cleared, so this one looks like it was just missed. The handler stays alive after the Network is closed and can still fire on a later navigation.

Adds the missing clearListener call, plus a test that closes the Network and checks that no event arrives.

🔧 Implementation Notes

Kept it in line with the existing clear calls, so there's no API change. BiDi.clearListener already checks isEventSubscribed first, so the extra call does nothing if onFetchError was never used.

The test is @Ignored on Chrome and Edge because they don't deliver network.fetchError at all, which is also why canListenToFetchError is annotated for them. @NotYetImplemented would be wrong here, since the harness treats those as expected to fail and this test passes. Firefox is where it actually runs.

🤖 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

💡 Additional Considerations

The JS binding has the same gap: bidi/network.js exposes fetchError() but its close() unsubscribes only the same four events. Java Script.close() also misses realmCreated / realmDestroyed. I left both out to keep this PR to one thing, happy to send follow-ups for either.

🔄 Types of changes

  • Bug fix (backwards compatible)

@CLAassistant

CLAassistant commented Aug 11, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@selenium-ci selenium-ci added C-java Java Bindings B-devtools Includes everything BiDi or Chrome DevTools related labels Aug 11, 2026
@qodo-code-review

Copy link
Copy Markdown
Contributor

PR Summary by Qodo

Clear BiDi fetchError listener when Network is closed

🐞 Bug fix 🧪 Tests 🕐 10-20 Minutes

Grey Divider

AI Description

• Clear the fetchError BiDi listener during Network.close().
• Prevent onFetchError callbacks from firing after try-with-resources cleanup.
• Add regression test ensuring no fetch error event is delivered post-close.
Diagram

graph TD
  T["NetworkEventsTest"] --> N["Network module"] --> B["BiDi session"] --> Br["Browser"]
  N --> L["Event listeners"]
  N --> C["Network.close()"] --> L
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Centralize listener cleanup (track subscriptions list)
  • ➕ Prevents future omissions when new events are added
  • ➕ Allows a single close path to iterate and clear all subscriptions
  • ➕ Reduces copy/paste parity bugs across modules (e.g., similar patterns in Script)
  • ➖ Requires refactor of listener registration paths
  • ➖ Slightly more indirection vs explicit clear calls
  • ➖ May touch more files and increase review surface

Recommendation: The current fix is the right minimal change for correctness: explicitly clearing the missing fetchError listener aligns with existing close() behavior and keeps the diff small. If additional similar omissions appear (as hinted in Script), consider a follow-up refactor to track subscriptions centrally and clear them generically to avoid parity regressions.

Files changed (2) +21 / -0

Bug fix (1) +1 / -0
Network.javaUnsubscribe fetchError listener during Network.close() +1/-0

Unsubscribe fetchError listener during Network.close()

• Adds a missing 'bidi.clearListener(fetchErrorEvent)' call in 'Network.close()'. This prevents fetchError callbacks from firing after the Network module is closed, matching cleanup behavior for other Network events.

java/src/org/openqa/selenium/bidi/module/Network.java

Tests (1) +20 / -0
NetworkEventsTest.javaRegression test: no fetchError event after Network is closed +20/-0

Regression test: no fetchError event after Network is closed

• Introduces a test that subscribes to 'onFetchError', closes the Network instance, then triggers a navigation expected to fail. The test asserts the listener is not invoked by verifying the future times out.

java/test/org/openqa/selenium/bidi/network/NetworkEventsTest.java

@qodo-code-review

qodo-code-review Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Code Review by Qodo

🐞 Bugs (1) 📘 Rule violations (2) 📜 Skill insights (0)

Grey Divider


Action required

1. Wrong NotYetImplemented usage ✓ Resolved 🐞 Bug ≡ Correctness
Description
The new test is annotated with @NotYetImplemented(CHROME/EDGE) but is written to pass when no
fetchError arrives; on those browsers a passing test is turned into a failure by
SeleniumExtension.afterEach ('marked as not yet implemented ... but already works'). This can break
Chrome/Edge CI for this PR.
Code

java/test/org/openqa/selenium/bidi/network/NetworkEventsTest.java[R179-182]

+  @NeedsFreshDriver
+  @NotYetImplemented(EDGE)
+  @NotYetImplemented(CHROME)
+  void doesNotReceiveFetchErrorAfterClose() {
Evidence
The test is annotated as NotYetImplemented for Chrome/Edge even though it expects a TimeoutException
(a passing condition). SeleniumExtension explicitly throws if a NotYetImplemented test did not fail,
which will make this test fail the run when it passes on those browsers.

java/test/org/openqa/selenium/bidi/network/NetworkEventsTest.java[178-195]
java/test/org/openqa/selenium/testing/SeleniumExtension.java[155-168]

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

### Issue description
`doesNotReceiveFetchErrorAfterClose` is marked with `@NotYetImplemented(CHROME)` and `@NotYetImplemented(EDGE)`, but the test asserts the *successful* behavior (no event after close). For Selenium’s test harness, `@NotYetImplemented` means “expected to fail”; if the test passes, `SeleniumExtension.afterEach` fails the run.

### Issue Context
This test is a regression check that should pass on browsers where the BiDi network fetchError subscription/unsubscription behavior is supported. On browsers where `network.fetchError` is not implemented, the test provides no signal (it will also pass), so it should be skipped/ignored there rather than marked as expected-failing.

### Fix Focus Areas
- java/test/org/openqa/selenium/bidi/network/NetworkEventsTest.java[178-195]

### Proposed fix
- Remove `@NotYetImplemented(CHROME)` / `@NotYetImplemented(EDGE)` from this new test, **or** replace them with `@Ignore(CHROME)` / `@Ignore(EDGE)` (and add the appropriate import) so the test is skipped instead of required to fail.

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



Remediation recommended

2. Network.close() missing Javadoc 📘 Rule violation ✧ Quality ⭐ New
Description
Network.close() is a public method that was modified in this change, but it has no Javadoc
comment. This violates the requirement that all changed public API methods in non-test code include
complete Javadoc.
Code

java/src/org/openqa/selenium/bidi/module/Network.java[200]

+    this.bidi.clearListener(fetchErrorEvent);
Evidence
PR Compliance ID 330201 requires all changed public methods in non-test code to have a Javadoc block
immediately above the method signature. In Network.java, public void close() (modified in this
PR) is preceded only by @Override and has no /** ... */ Javadoc comment.

Rule 330201: Require complete Javadoc on public API methods
java/src/org/openqa/selenium/bidi/module/Network.java[197-204]

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

## Issue description
`Network.close()` is a changed public API method in non-test code but has no Javadoc block comment, which violates the requirement for complete Javadoc on public API methods.

## Issue Context
The method is `public` and was modified in this PR (added `clearListener(fetchErrorEvent)`), so it falls under the “changed public method” scope.

## Fix Focus Areas
- java/src/org/openqa/selenium/bidi/module/Network.java[197-204]

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


3. Bounded wait false-negative ✓ Resolved 🐞 Bug ☼ Reliability
Description
doesNotReceiveFetchErrorAfterClose treats “no event within 2s” as proof that a closed Network will
never receive network.fetchError, so a late-delivered event (e.g., delayed dispatch) would not be
detected. This reduces the test’s ability to catch regressions reliably compared to the existing
fetchError test that allows 5s for delivery.
Code

java/test/org/openqa/selenium/bidi/network/NetworkEventsTest.java[R197-198]

+    assertThatThrownBy(() -> future.get(2, TimeUnit.SECONDS))
+        .isInstanceOf(TimeoutException.class);
Evidence
The new test only waits 2 seconds for future.get(...) to time out, while the existing fetchError
test in the same file waits 5 seconds for fetchError delivery. Also, BiDi event handling is
dispatched asynchronously, so callback delivery can be delayed relative to the triggering
navigation.

java/test/org/openqa/selenium/bidi/network/NetworkEventsTest.java[184-199]
java/test/org/openqa/selenium/bidi/network/NetworkEventsTest.java[158-169]
java/src/org/openqa/selenium/bidi/Connection.java[274-285]

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

### Issue description
`doesNotReceiveFetchErrorAfterClose()` only waits 2 seconds for a `FetchError` event to arrive and considers that sufficient to prove listener cleanup. If `network.fetchError` is delivered after that window, the test becomes a false negative.

### Issue Context
The same test class already uses a 5-second timeout to wait for `network.fetchError` in `canListenToFetchError()`, suggesting that event delivery is allowed to take longer than 2 seconds in this suite.

### Fix Focus Areas
- java/test/org/openqa/selenium/bidi/network/NetworkEventsTest.java[197-198]

### Suggested change
Increase the timeout window (e.g., align it to 5 seconds like the positive fetchError test) so the regression test is less likely to miss a late event.

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


4. Vacuous test on navigation failure ✓ Resolved 🐞 Bug ☼ Reliability
Description
doesNotReceiveFetchErrorAfterClose swallows any WebDriverException from driver.get() and then only
asserts that the fetchError future times out, so it can pass even if navigation failed for unrelated
reasons (e.g., session lost) or didn’t meaningfully exercise fetchError delivery.
Code

java/test/org/openqa/selenium/bidi/network/NetworkEventsTest.java[R189-192]

+    try {
+      driver.get("https://not_a_valid_url.test/");
+    } catch (WebDriverException ignored) {
+    }
Evidence
The test ignores all WebDriverException during navigation and then only checks for a
TimeoutException from future.get, so unrelated navigation/driver failures can still produce a
passing test. NoSuchSessionException is a WebDriverException subtype and would be swallowed by the
current catch block.

java/test/org/openqa/selenium/bidi/network/NetworkEventsTest.java[183-196]
java/src/org/openqa/selenium/NoSuchSessionException.java[20-31]
java/test/org/openqa/selenium/bidi/network/NetworkEventsTest.java[153-176]

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

### Issue description
`doesNotReceiveFetchErrorAfterClose()` catches and ignores *all* `WebDriverException` from `driver.get(...)`, then asserts only that `future.get(...)` times out. This can make the test pass even when the navigation failed for unrelated reasons (e.g. `NoSuchSessionException`) or otherwise didn’t execute the intended invalid-host scenario.

### Issue Context
The navigation is intentionally to an invalid URL, so some exception handling is expected. The fix is to keep the exception handling, but narrow/validate it so unrelated driver/session failures do not get masked.

### Fix Focus Areas
- java/test/org/openqa/selenium/bidi/network/NetworkEventsTest.java[189-195]

### Suggested fix
- Replace the broad `catch (WebDriverException ignored)` with logic that:
 - explicitly fails if no exception is thrown (so the invalid-host trigger actually happened), OR
 - rethrows specific session-fatal exceptions (e.g. `NoSuchSessionException`), and
 - optionally asserts something about the exception to ensure it’s the expected navigation failure.

Example approach:
```java
try {
 driver.get("https://not_a_valid_url.test/");
 fail("Expected navigation to invalid URL to fail");
} catch (NoSuchSessionException e) {
 throw e;
} catch (WebDriverException expected) {
 // expected navigation failure
}
```
(Adjust imports as needed.)

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


View review recommended (2)
5. Cross-binding Network.close() mismatch 📘 Rule violation ≡ Correctness
Description
Java Network.close() now clears fetchErrorEvent, but the JavaScript BiDi Network.close() still
unsubscribes only four network events and does not include network.fetchError. This risks
user-visible divergence across bindings unless aligned or explicitly documented as intentional.
Code

java/src/org/openqa/selenium/bidi/module/Network.java[200]

+    this.bidi.clearListener(fetchErrorEvent);
Evidence
The checklist requires cross-language comparison for user-visible binding behavior changes. The diff
shows Java Network.close() now clears fetchErrorEvent, while the JavaScript binding’s
Network.close() unsubscribes from network.beforeRequestSent, network.responseStarted,
network.responseCompleted, and network.authRequired but not network.fetchError, indicating
inconsistent behavior across bindings.

Rule 389265: Compare cross-language bindings when changing user-visible behavior
java/src/org/openqa/selenium/bidi/module/Network.java[198-203]
javascript/selenium-webdriver/bidi/network.js[401-422]

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

## Issue description
The Java BiDi `Network.close()` behavior changed to clear the `network.fetchError` listener, but the JavaScript binding’s `Network.close()` does not unsubscribe from `network.fetchError`, creating a cross-language behavior mismatch.

## Issue Context
PR Compliance requires comparing other bindings for user-visible behavior changes and either keeping behavior consistent or documenting intentional divergence.

## Fix Focus Areas
- java/src/org/openqa/selenium/bidi/module/Network.java[198-203]
- java/test/org/openqa/selenium/bidi/network/NetworkEventsTest.java[179-196]
- javascript/selenium-webdriver/bidi/network.js[401-422]

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


6. Close clears shared fetchError 🐞 Bug ≡ Correctness
Description
Network.close() now calls bidi.clearListener(fetchErrorEvent), which unsubscribes the
'network.fetchError' event by event name and removes all callbacks for that event from the shared
BiDi connection. Closing one Network instance can therefore disable other fetchError listeners still
in use on the same connection.
Code

java/src/org/openqa/selenium/bidi/module/Network.java[200]

+    this.bidi.clearListener(fetchErrorEvent);
Evidence
The added clearListener(fetchErrorEvent) triggers BiDi.clearListener(Event), which unsubscribes by
event name and clears the entire callback map for that event, so it affects other listeners beyond
the closing Network instance; Network.onFetchError also does not retain subscription ids, preventing
scoped removal.

java/src/org/openqa/selenium/bidi/module/Network.java[165-170]
java/src/org/openqa/selenium/bidi/module/Network.java[197-204]
java/src/org/openqa/selenium/bidi/BiDi.java[86-93]
java/src/org/openqa/selenium/bidi/BiDi.java[141-149]
java/src/org/openqa/selenium/bidi/Connection.java[192-199]

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

### Issue description
`Network.close()` uses `bidi.clearListener(fetchErrorEvent)`, which unsubscribes by event name and clears *all* callbacks registered for `network.fetchError` on the shared `BiDi` connection. This can break other components/tests that still have active `network.fetchError` listeners when any `Network` instance is closed.

### Issue Context
- `Network.onFetchError(...)` calls `bidi.addListener(...)` but does not retain the returned subscription id, so `close()` cannot currently unsubscribe only the listener(s) created by this `Network` instance.
- `BiDi.clearListener(Event)` performs `session.unsubscribe` by `events:[eventMethod]` and then `connection.clearListener(event)` drops the entire callback map for that event.

### Fix Focus Areas
- java/src/org/openqa/selenium/bidi/module/Network.java[157-204]

### Suggested fix approach
1. In `Network`, store the subscription id(s) returned by `bidi.addListener(...)` when registering `fetchErrorEvent` (and ideally the other events too for consistency).
2. In `close()`, call `bidi.removeListener(subscriptionId)` for the stored id(s) instead of `bidi.clearListener(fetchErrorEvent)`.
3. (Optional but recommended) Add/adjust a regression test for the multi-listener case: register `fetchError` on one `Network`, create and close a second `Network`, then verify the first still receives a `fetchError` event (skip browsers where `network.fetchError` is not delivered).

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


Grey Divider

Context
✅ Compliance rules (platform): 18 rules

Grey Divider

Tip of the day
💡 Did you know, you can group findings by type and pick your Finding display, from Minimal to Full

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Previous review results

Review updated until commit a2b984f ⚖️ Balanced

Results up to commit 1068ecd ⚖️ Balanced


🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0) 🎨 UX issues (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)


Action required
1. Wrong NotYetImplemented usage ✓ Resolved 🐞 Bug ≡ Correctness
Description
The new test is annotated with @NotYetImplemented(CHROME/EDGE) but is written to pass when no
fetchError arrives; on those browsers a passing test is turned into a failure by
SeleniumExtension.afterEach ('marked as not yet implemented ... but already works'). This can break
Chrome/Edge CI for this PR.
Code

java/test/org/openqa/selenium/bidi/network/NetworkEventsTest.java[R179-182]

+  @NeedsFreshDriver
+  @NotYetImplemented(EDGE)
+  @NotYetImplemented(CHROME)
+  void doesNotReceiveFetchErrorAfterClose() {
Evidence
The test is annotated as NotYetImplemented for Chrome/Edge even though it expects a TimeoutException
(a passing condition). SeleniumExtension explicitly throws if a NotYetImplemented test did not fail,
which will make this test fail the run when it passes on those browsers.

java/test/org/openqa/selenium/bidi/network/NetworkEventsTest.java[178-195]
java/test/org/openqa/selenium/testing/SeleniumExtension.java[155-168]

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

### Issue description
`doesNotReceiveFetchErrorAfterClose` is marked with `@NotYetImplemented(CHROME)` and `@NotYetImplemented(EDGE)`, but the test asserts the *successful* behavior (no event after close). For Selenium’s test harness, `@NotYetImplemented` means “expected to fail”; if the test passes, `SeleniumExtension.afterEach` fails the run.

### Issue Context
This test is a regression check that should pass on browsers where the BiDi network fetchError subscription/unsubscription behavior is supported. On browsers where `network.fetchError` is not implemented, the test provides no signal (it will also pass), so it should be skipped/ignored there rather than marked as expected-failing.

### Fix Focus Areas
- java/test/org/openqa/selenium/bidi/network/NetworkEventsTest.java[178-195]

### Proposed fix
- Remove `@NotYetImplemented(CHROME)` / `@NotYetImplemented(EDGE)` from this new test, **or** replace them with `@Ignore(CHROME)` / `@Ignore(EDGE)` (and add the appropriate import) so the test is skipped instead of required to fail.

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


Results up to commit abc7ffa ⚖️ Balanced


No changes from previous review

Results up to commit 0a615a0 ⚖️ Balanced


🐞 Bugs (1) 📘 Rule violations (0) 📎 Requirement gaps (0) 🎨 UX issues (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)


Remediation recommended
1. Close clears shared fetchError 🐞 Bug ≡ Correctness
Description
Network.close() now calls bidi.clearListener(fetchErrorEvent), which unsubscribes the
'network.fetchError' event by event name and removes all callbacks for that event from the shared
BiDi connection. Closing one Network instance can therefore disable other fetchError listeners still
in use on the same connection.
Code

java/src/org/openqa/selenium/bidi/module/Network.java[200]

+    this.bidi.clearListener(fetchErrorEvent);
Evidence
The added clearListener(fetchErrorEvent) triggers BiDi.clearListener(Event), which unsubscribes by
event name and clears the entire callback map for that event, so it affects other listeners beyond
the closing Network instance; Network.onFetchError also does not retain subscription ids, preventing
scoped removal.

java/src/org/openqa/selenium/bidi/module/Network.java[165-170]
java/src/org/openqa/selenium/bidi/module/Network.java[197-204]
java/src/org/openqa/selenium/bidi/BiDi.java[86-93]
java/src/org/openqa/selenium/bidi/BiDi.java[141-149]
java/src/org/openqa/selenium/bidi/Connection.java[192-199]

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

### Issue description
`Network.close()` uses `bidi.clearListener(fetchErrorEvent)`, which unsubscribes by event name and clears *all* callbacks registered for `network.fetchError` on the shared `BiDi` connection. This can break other components/tests that still have active `network.fetchError` listeners when any `Network` instance is closed.

### Issue Context
- `Network.onFetchError(...)` calls `bidi.addListener(...)` but does not retain the returned subscription id, so `close()` cannot currently unsubscribe only the listener(s) created by this `Network` instance.
- `BiDi.clearListener(Event)` performs `session.unsubscribe` by `events:[eventMethod]` and then `connection.clearListener(event)` drops the entire callback map for that event.

### Fix Focus Areas
- java/src/org/openqa/selenium/bidi/module/Network.java[157-204]

### Suggested fix approach
1. In `Network`, store the subscription id(s) returned by `bidi.addListener(...)` when registering `fetchErrorEvent` (and ideally the other events too for consistency).
2. In `close()`, call `bidi.removeListener(subscriptionId)` for the stored id(s) instead of `bidi.clearListener(fetchErrorEvent)`.
3. (Optional but recommended) Add/adjust a regression test for the multi-listener case: register `fetchError` on one `Network`, create and close a second `Network`, then verify the first still receives a `fetchError` event (skip browsers where `network.fetchError` is not delivered).

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


Results up to commit 9d55e05 ⚖️ Balanced


🐞 Bugs (0) 📘 Rule violations (1) 📎 Requirement gaps (0) 🎨 UX issues (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)


Remediation recommended
1. Cross-binding Network.close() mismatch 📘 Rule violation ≡ Correctness
Description
Java Network.close() now clears fetchErrorEvent, but the JavaScript BiDi Network.close() still
unsubscribes only four network events and does not include network.fetchError. This risks
user-visible divergence across bindings unless aligned or explicitly documented as intentional.
Code

java/src/org/openqa/selenium/bidi/module/Network.java[200]

+    this.bidi.clearListener(fetchErrorEvent);
Evidence
The checklist requires cross-language comparison for user-visible binding behavior changes. The diff
shows Java Network.close() now clears fetchErrorEvent, while the JavaScript binding’s
Network.close() unsubscribes from network.beforeRequestSent, network.responseStarted,
network.responseCompleted, and network.authRequired but not network.fetchError, indicating
inconsistent behavior across bindings.

Rule 389265: Compare cross-language bindings when changing user-visible behavior
java/src/org/openqa/selenium/bidi/module/Network.java[198-203]
javascript/selenium-webdriver/bidi/network.js[401-422]

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

## Issue description
The Java BiDi `Network.close()` behavior changed to clear the `network.fetchError` listener, but the JavaScript binding’s `Network.close()` does not unsubscribe from `network.fetchError`, creating a cross-language behavior mismatch.

## Issue Context
PR Compliance requires comparing other bindings for user-visible behavior changes and either keeping behavior consistent or documenting intentional divergence.

## Fix Focus Areas
- java/src/org/openqa/selenium/bidi/module/Network.java[198-203]
- java/test/org/openqa/selenium/bidi/network/NetworkEventsTest.java[179-196]
- javascript/selenium-webdriver/bidi/network.js[401-422]

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


2. Vacuous test on navigation failure ✓ Resolved 🐞 Bug ☼ Reliability
Description
doesNotReceiveFetchErrorAfterClose swallows any WebDriverException from driver.get() and then only
asserts that the fetchError future times out, so it can pass even if navigation failed for unrelated
reasons (e.g., session lost) or didn’t meaningfully exercise fetchError delivery.
Code

java/test/org/openqa/selenium/bidi/network/NetworkEventsTest.java[R189-192]

+    try {
+      driver.get("https://not_a_valid_url.test/");
+    } catch (WebDriverException ignored) {
+    }
Evidence
The test ignores all WebDriverException during navigation and then only checks for a
TimeoutException from future.get, so unrelated navigation/driver failures can still produce a
passing test. NoSuchSessionException is a WebDriverException subtype and would be swallowed by the
current catch block.

java/test/org/openqa/selenium/bidi/network/NetworkEventsTest.java[183-196]
java/src/org/openqa/selenium/NoSuchSessionException.java[20-31]
java/test/org/openqa/selenium/bidi/network/NetworkEventsTest.java[153-176]

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

### Issue description
`doesNotReceiveFetchErrorAfterClose()` catches and ignores *all* `WebDriverException` from `driver.get(...)`, then asserts only that `future.get(...)` times out. This can make the test pass even when the navigation failed for unrelated reasons (e.g. `NoSuchSessionException`) or otherwise didn’t execute the intended invalid-host scenario.

### Issue Context
The navigation is intentionally to an invalid URL, so some exception handling is expected. The fix is to keep the exception handling, but narrow/validate it so unrelated driver/session failures do not get masked.

### Fix Focus Areas
- java/test/org/openqa/selenium/bidi/network/NetworkEventsTest.java[189-195]

### Suggested fix
- Replace the broad `catch (WebDriverException ignored)` with logic that:
 - explicitly fails if no exception is thrown (so the invalid-host trigger actually happened), OR
 - rethrows specific session-fatal exceptions (e.g. `NoSuchSessionException`), and
 - optionally asserts something about the exception to ensure it’s the expected navigation failure.

Example approach:
```java
try {
 driver.get("https://not_a_valid_url.test/");
 fail("Expected navigation to invalid URL to fail");
} catch (NoSuchSessionException e) {
 throw e;
} catch (WebDriverException expected) {
 // expected navigation failure
}
```
(Adjust imports as needed.)

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


Results up to commit d67b0db ⚖️ Balanced


🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0) 🎨 UX issues (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)


Remediation recommended
1. Bounded wait false-negative ✓ Resolved 🐞 Bug ☼ Reliability
Description
doesNotReceiveFetchErrorAfterClose treats “no event within 2s” as proof that a closed Network will
never receive network.fetchError, so a late-delivered event (e.g., delayed dispatch) would not be
detected. This reduces the test’s ability to catch regressions reliably compared to the existing
fetchError test that allows 5s for delivery.
Code

java/test/org/openqa/selenium/bidi/network/NetworkEventsTest.java[R197-198]

+    assertThatThrownBy(() -> future.get(2, TimeUnit.SECONDS))
+        .isInstanceOf(TimeoutException.class);
Evidence
The new test only waits 2 seconds for future.get(...) to time out, while the existing fetchError
test in the same file waits 5 seconds for fetchError delivery. Also, BiDi event handling is
dispatched asynchronously, so callback delivery can be delayed relative to the triggering
navigation.

java/test/org/openqa/selenium/bidi/network/NetworkEventsTest.java[184-199]
java/test/org/openqa/selenium/bidi/network/NetworkEventsTest.java[158-169]
java/src/org/openqa/selenium/bidi/Connection.java[274-285]

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

### Issue description
`doesNotReceiveFetchErrorAfterClose()` only waits 2 seconds for a `FetchError` event to arrive and considers that sufficient to prove listener cleanup. If `network.fetchError` is delivered after that window, the test becomes a false negative.

### Issue Context
The same test class already uses a 5-second timeout to wait for `network.fetchError` in `canListenToFetchError()`, suggesting that event delivery is allowed to take longer than 2 seconds in this suite.

### Fix Focus Areas
- java/test/org/openqa/selenium/bidi/network/NetworkEventsTest.java[197-198]

### Suggested change
Increase the timeout window (e.g., align it to 5 seconds like the positive fetchError test) so the regression test is less likely to miss a late event.

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


Qodo Logo

Comment thread java/test/org/openqa/selenium/bidi/network/NetworkEventsTest.java
@qodo-code-review

Copy link
Copy Markdown
Contributor

Code review by qodo was updated up to the latest commit abc7ffa

@Mochxd
Mochxd force-pushed the fix-bidi-network-close-fetch-error branch from abc7ffa to 0a615a0 Compare August 11, 2026 20:42
@Override
public void close() {
this.bidi.clearListener(beforeRequestSentEvent);
this.bidi.clearListener(fetchErrorEvent);

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.

Remediation recommended

1. Close clears shared fetcherror 🐞 Bug ≡ Correctness

Network.close() now calls bidi.clearListener(fetchErrorEvent), which unsubscribes the
'network.fetchError' event by event name and removes all callbacks for that event from the shared
BiDi connection. Closing one Network instance can therefore disable other fetchError listeners still
in use on the same connection.
Agent Prompt
### Issue description
`Network.close()` uses `bidi.clearListener(fetchErrorEvent)`, which unsubscribes by event name and clears *all* callbacks registered for `network.fetchError` on the shared `BiDi` connection. This can break other components/tests that still have active `network.fetchError` listeners when any `Network` instance is closed.

### Issue Context
- `Network.onFetchError(...)` calls `bidi.addListener(...)` but does not retain the returned subscription id, so `close()` cannot currently unsubscribe only the listener(s) created by this `Network` instance.
- `BiDi.clearListener(Event)` performs `session.unsubscribe` by `events:[eventMethod]` and then `connection.clearListener(event)` drops the entire callback map for that event.

### Fix Focus Areas
- java/src/org/openqa/selenium/bidi/module/Network.java[157-204]

### Suggested fix approach
1. In `Network`, store the subscription id(s) returned by `bidi.addListener(...)` when registering `fetchErrorEvent` (and ideally the other events too for consistency).
2. In `close()`, call `bidi.removeListener(subscriptionId)` for the stored id(s) instead of `bidi.clearListener(fetchErrorEvent)`.
3. (Optional but recommended) Add/adjust a regression test for the multi-listener case: register `fetchError` on one `Network`, create and close a second `Network`, then verify the first still receives a `fetchError` event (skip browsers where `network.fetchError` is not delivered).

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

@qodo-code-review

Copy link
Copy Markdown
Contributor

Code review by qodo was updated up to the latest commit 0a615a0

@Mochxd
Mochxd force-pushed the fix-bidi-network-close-fetch-error branch from 0a615a0 to 9d55e05 Compare August 11, 2026 20:56
@Override
public void close() {
this.bidi.clearListener(beforeRequestSentEvent);
this.bidi.clearListener(fetchErrorEvent);

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.

Remediation recommended

1. Cross-binding network.close() mismatch 📘 Rule violation ≡ Correctness

Java Network.close() now clears fetchErrorEvent, but the JavaScript BiDi Network.close() still
unsubscribes only four network events and does not include network.fetchError. This risks
user-visible divergence across bindings unless aligned or explicitly documented as intentional.
Agent Prompt
## Issue description
The Java BiDi `Network.close()` behavior changed to clear the `network.fetchError` listener, but the JavaScript binding’s `Network.close()` does not unsubscribe from `network.fetchError`, creating a cross-language behavior mismatch.

## Issue Context
PR Compliance requires comparing other bindings for user-visible behavior changes and either keeping behavior consistent or documenting intentional divergence.

## Fix Focus Areas
- java/src/org/openqa/selenium/bidi/module/Network.java[198-203]
- java/test/org/openqa/selenium/bidi/network/NetworkEventsTest.java[179-196]
- javascript/selenium-webdriver/bidi/network.js[401-422]

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

Comment thread java/test/org/openqa/selenium/bidi/network/NetworkEventsTest.java
@qodo-code-review

Copy link
Copy Markdown
Contributor

Code review by qodo was updated up to the latest commit 9d55e05

@Mochxd
Mochxd force-pushed the fix-bidi-network-close-fetch-error branch from 9d55e05 to d67b0db Compare August 11, 2026 21:06
Comment thread java/test/org/openqa/selenium/bidi/network/NetworkEventsTest.java Outdated
@qodo-code-review

Copy link
Copy Markdown
Contributor

Code review by qodo was updated up to the latest commit d67b0db

@Mochxd
Mochxd force-pushed the fix-bidi-network-close-fetch-error branch from d67b0db to a2b984f Compare August 11, 2026 21:12
@Override
public void close() {
this.bidi.clearListener(beforeRequestSentEvent);
this.bidi.clearListener(fetchErrorEvent);

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.

Remediation recommended

1. network.close() missing javadoc 📘 Rule violation ✧ Quality

Network.close() is a public method that was modified in this change, but it has no Javadoc
comment. This violates the requirement that all changed public API methods in non-test code include
complete Javadoc.
Agent Prompt
## Issue description
`Network.close()` is a changed public API method in non-test code but has no Javadoc block comment, which violates the requirement for complete Javadoc on public API methods.

## Issue Context
The method is `public` and was modified in this PR (added `clearListener(fetchErrorEvent)`), so it falls under the “changed public method” scope.

## Fix Focus Areas
- java/src/org/openqa/selenium/bidi/module/Network.java[197-204]

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

@qodo-code-review

Copy link
Copy Markdown
Contributor

Code review by qodo was updated up to the latest commit a2b984f

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

Labels

B-devtools Includes everything BiDi or Chrome DevTools related C-java Java Bindings

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants