fix: Handle WSClient write failure when server closes WebSocket#6671
Merged
fix: Handle WSClient write failure when server closes WebSocket#6671
Conversation
…-5573) Use the error_code overload of write_some in WSClientImpl::invoke() to gracefully handle the case where the server has already closed the WebSocket connection (e.g. after booting a client that exceeded resource thresholds). This prevents an unhandled "Operation canceled" exception that intermittently fails xrpl.rpc.RPCOverload in CI. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## develop #6671 +/- ##
=========================================
- Coverage 81.4% 81.4% -0.0%
=========================================
Files 998 998
Lines 74443 74443
Branches 7563 7562 -1
=========================================
- Hits 60632 60624 -8
- Misses 13811 13819 +8 🚀 New features to boost your workflow:
|
bthomee
approved these changes
Mar 26, 2026
Contributor
There was a problem hiding this comment.
Pull request overview
Fixes an intermittent unit test failure in the WebSocket-based test client (WSClientImpl) by preventing an exception from escaping when the server has already initiated WebSocket close (e.g., booting an overloaded client).
Changes:
- Switch
WSClientImpl::invoke()from the throwingws_.write_some()overload to theerror_codeoverload. - On write failure, return an empty
Json::Value(null) to match existing “no response” behavior (e.g.,findMsg()timeout), allowing theRPCOverloadtest to treat it as “booted”.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
mvadari
pushed a commit
that referenced
this pull request
Apr 7, 2026
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
abrahim-djordjevic
pushed a commit
to abrahim-djordjevic/rippled
that referenced
this pull request
Apr 7, 2026
…F#6671) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
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.
High Level Overview of Change
Fix intermittent
xrpl.rpc.RPCOverloadtest failure caused by an unhandled exception inWSClientImpl::invoke()when the server closes the WebSocket connection after booting an overloaded client.Context of Change
Failing CI job: https://github.com/XRPLF/rippled/actions/runs/23560752956/job/68599747791
The bug was introduced when the test infrastructure was originally written.
WSClientImpl::invoke()uses the throwing overload ofws_.write_some(). When the server boots a client for exceeding resource thresholds (session->close({policy_error, "threshold exceeded"})inServerHandler::processSession), a WebSocket close frame is sent. There is a race between:invoke()→write_some()on the next loop iterationIf
write_some()executes before the async read handler (on_read_msg) processes the close frame, Beast's internalcheck_stop_now()throwsOperation canceled [system:125]. Sinceinvoke()has no exception handling around the write, this propagates as an unhandled exception.The fix replaces the throwing
write_someoverload with theerror_codeoverload. On write failure,invoke()returns{}(emptyJson::Value) — the same return value it already produces whenfindMsg()times out. TheRPCOverloadtest already handles this correctly:if (jv.isNull()) { booted = true; }.Observed in CI job
rhel-10-clang-any-amd64-release(PR #6619 merge queue run, 2026-03-25):API Impact
None — this change is limited to test infrastructure (
src/test/jtx/impl/WSClient.cpp).