Skip to content

Conversation

@asolntsev
Copy link
Contributor

@asolntsev asolntsev commented Dec 27, 2025

User description

  • Some responses don't contain the required field "error" - just treat them as "unknown error"
  • If response doesn't contain the required field "message", just write the whole response as the message.

🔗 Related Issues

Improves #16389

🔄 Types of changes

  • New feature (non-breaking change which adds functionality and tests!)

PR Type

Bug fix, Tests


Description

  • Handle remote responses missing required "error" field gracefully

  • Use response toString as fallback when "message" field missing

  • Create InvalidResponseException for malformed response detection

  • Add comprehensive test coverage for edge cases


Diagram Walkthrough

flowchart LR
  A["Remote Response"] --> B{"Has 'value' field?"}
  B -->|No| C["Throw InvalidResponseException"]
  B -->|Yes| D{"Has 'error' field?"}
  D -->|No| E["Use empty string as error"]
  D -->|Yes| F{"Error is String?"}
  F -->|No| C
  F -->|Yes| G{"Match known error?"}
  G -->|Yes| H["Create specific exception"]
  G -->|No| I["Create WebDriverException with error code"]
  E --> J{"Has 'message' field?"}
  J -->|No| K["Use response toString"]
  J -->|Yes| L{"Message is String?"}
  L -->|No| C
  L -->|Yes| M["Use message value"]
Loading

File Walkthrough

Relevant files
Bug fix
ErrorCodec.java
Improve remote response error handling robustness               

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

  • Added imports for requireNonNullElse, requireNonNullElseGet, and
    Optional
  • Replaced hardcoded "unknown error" with DEFAULT_ERROR constant
  • Modified decode() method to handle missing "error" and "message"
    fields
  • Changed exception type from IllegalArgumentException to
    InvalidResponseException
  • Added fallback logic to use response toString when message is missing
  • Enhanced unknown error handling to include error code in exception
    message
+21/-13 
Enhancement
InvalidResponseException.java
New exception for malformed remote responses                         

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

  • New exception class extending IllegalArgumentException
  • Formats error messages with response details and W3C spec reference
  • Includes reference link to W3C WebDriver specification
+30/-0   
Tests
ErrorCodecTest.java
Add tests for edge case response handling                               

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

  • Added static imports for AssertJ assertions
  • Added test for W3C compliant response decoding
  • Added test for unknown error code handling with error code in message
  • Added test for missing "value" field validation
  • Added test for missing "error" field tolerance
  • Updated existing assertion calls to use static imports
+47/-3   

* Some responses don't contain the required field "error" - just treat them as "unknown error"
* If response doesn't contain the required field "message", just write the whole response as the message.
@selenium-ci selenium-ci added the C-java Java Bindings label Dec 27, 2025
@qodo-code-review
Copy link
Contributor

PR Compliance Guide 🔍

Below is a summary of compliance checks for this PR:

Security Compliance
Sensitive data exposure

Description: The new fallback/exception paths embed the entire remote response (via response::toString)
and include remote-provided fields (message, error) in exception messages, which can leak
sensitive data (e.g., session IDs, capabilities, tokens, internal URLs) into logs or error
reporting when these exceptions are propagated/recorded.
ErrorCodec.java [151-172]

Referred Code
  throw new InvalidResponseException("missing \"value\" field", response);
}

Map<?, ?> value = (Map<?, ?>) response.get("value");

Object error = requireNonNullElse(value.get("error"), "");
Object message = requireNonNullElseGet(value.get("message"), response::toString);

if (!(error instanceof String)) {
  throw new InvalidResponseException("\"error\" field must be a string", response);
}
if (!(message instanceof String)) {
  throw new InvalidResponseException("\"message\" field must be a string", response);
}

Optional<W3CError<? extends WebDriverException>> w3CError =
    ERRORS.stream().filter(err -> error.equals(err.w3cErrorString)).findFirst();
if (w3CError.isPresent()) {
  return w3CError.get().exceptionConstructor.apply((String) message);
}
String extendedMessage = String.format("%s (error code: \"%s\")", message, error);


 ... (clipped 1 lines)
Ticket Compliance
🎫 No ticket provided
  • Create ticket/issue
Codebase Duplication Compliance
Codebase context is not defined

Follow the guide to enable codebase context checks.

Custom Compliance
🟢
Generic: Comprehensive Audit Trails

Objective: To create a detailed and reliable record of critical system actions for security analysis
and compliance.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Meaningful Naming and Self-Documenting Code

Objective: Ensure all identifiers clearly express their purpose and intent, making code
self-documenting

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Robust Error Handling and Edge Case Management

Objective: Ensure comprehensive error handling that provides meaningful context and graceful
degradation

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Logging Practices

Objective: To ensure logs are useful for debugging and auditing without exposing sensitive
information like PII, PHI, or cardholder data.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Security-First Input Validation and Data Handling

Objective: Ensure all data inputs are validated, sanitized, and handled securely to prevent
vulnerabilities

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

🔴
Generic: Secure Error Handling

Objective: To prevent the leakage of sensitive system information through error messages while
providing sufficient detail for internal debugging.

Status:
Sensitive data exposure: The exception message embeds the full response map (and may also embed it via fallback
response::toString), which can leak sensitive remote/server details to callers.

Referred Code
public InvalidResponseException(String message, Map<String, Object> response) {
  super(String.format("%s: %s%nSee %s", message, response, w3cErrorFormat));
}

Learn more about managing compliance generic rules or creating your own custom rules

Compliance status legend 🟢 - Fully Compliant
🟡 - Partial Compliant
🔴 - Not Compliant
⚪ - Requires Further Human Verification
🏷️ - Compliance label

@qodo-code-review
Copy link
Contributor

PR Code Suggestions ✨

Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
General
Use value map for message fallback

When the "message" field is missing, use the string representation of the inner
value map for the fallback message instead of the entire response map.

java/src/org/openqa/selenium/remote/ErrorCodec.java [157]

-Object message = requireNonNullElseGet(value.get("message"), response::toString);
+Object message = requireNonNullElseGet(value.get("message"), () -> String.valueOf(value));
  • Apply / Chat
Suggestion importance[1-10]: 6

__

Why: The suggestion correctly points out that using the entire response map as a fallback for a missing message is not ideal. Using the inner value map provides a more focused and relevant context in the exception message, which is a significant improvement for debugging.

Low
Learned
best practice
Limit raw response in errors

Avoid embedding the full raw response map in the exception message; instead
include a bounded/sanitized representation (e.g., only top-level keys or a
truncated string) to reduce risk from untrusted remote data.

java/src/org/openqa/selenium/remote/InvalidResponseException.java [27-29]

 public InvalidResponseException(String message, Map<String, Object> response) {
-  super(String.format("%s: %s%nSee %s", message, response, w3cErrorFormat));
+  String responseSummary = String.valueOf(response.keySet());
+  super(String.format("%s: keys=%s%nSee %s", message, responseSummary, w3cErrorFormat));
 }

[To ensure code accuracy, apply this suggestion manually]

Suggestion importance[1-10]: 6

__

Why:
Relevant best practice - Validate and sanitize external inputs before including them in exception messages to avoid logging excessive or untrusted raw data.

Low
Possible issue
Handle empty error strings directly

Add a check for an empty error string to avoid appending (error code: "") to the
exception message, returning a cleaner message instead.

java/src/org/openqa/selenium/remote/ErrorCodec.java [156-172]

-Object error = requireNonNullElse(value.get("error"), "");
-Object message = requireNonNullElseGet(value.get("message"), response::toString);
+Object errorObj = requireNonNullElse(value.get("error"), "");
+Object messageObj = requireNonNullElseGet(value.get("message"), response::toString);
 
-if (!(error instanceof String)) {
+if (!(errorObj instanceof String)) {
   throw new InvalidResponseException("\"error\" field must be a string", response);
 }
-if (!(message instanceof String)) {
+if (!(messageObj instanceof String)) {
   throw new InvalidResponseException("\"message\" field must be a string", response);
+}
+
+String error = (String) errorObj;
+String message = (String) messageObj;
+
+if (error.isEmpty()) {
+  return DEFAULT_ERROR.exceptionConstructor.apply(message);
 }
 
 Optional<W3CError<? extends WebDriverException>> w3CError =
     ERRORS.stream().filter(err -> error.equals(err.w3cErrorString)).findFirst();
 if (w3CError.isPresent()) {
-  return w3CError.get().exceptionConstructor.apply((String) message);
+  return w3CError.get().exceptionConstructor.apply(message);
 }
 String extendedMessage = String.format("%s (error code: \"%s\")", message, error);
 return DEFAULT_ERROR.exceptionConstructor.apply(extendedMessage);
  • Apply / Chat
Suggestion importance[1-10]: 5

__

Why: This suggestion correctly identifies that an empty error string results in a suboptimal exception message like (error code: ""). The proposed change to handle this edge case explicitly improves the clarity of the exception message, making it more user-friendly.

Low
  • More

@asolntsev asolntsev self-assigned this Dec 27, 2025
@cgoldberg cgoldberg changed the title #16389 be more tolerant to remote responses [java] Be more tolerant to remote responses Dec 27, 2025
@asolntsev asolntsev added this to the 4.40.0 milestone Dec 29, 2025
@asolntsev asolntsev merged commit 01200af into SeleniumHQ:trunk Dec 29, 2025
44 of 45 checks passed
@asolntsev asolntsev deleted the fix/16389-handle-unexpected-remote-response branch December 29, 2025 18:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[🐛 Bug]: Randomly getting java.lang.ClassCastException when trying to interact with a particular element

2 participants