Repository navigation
Robustness fixes for multiple issues #6969
Description
Activity
Thanks for consolidating these findings. I confirmed that the referenced code patterns exist, but the scope and verification plan should be tightened before implementation.
- For
EffectiveCheckService, please provide a reproducible path where a non-cancelled, unsuccessfulChannelFuturehas a null cause. A listener is normally invoked after completion, so this may be defensive hardening rather than a reachable defect. Cleanup should be protected withfinallyregardless. - HELLO validation should happen before full message rendering and, ideally, before
updateNodeIdor any other peer-state mutation. Please add tests for invalid and boundary-sized fields. - The
QpsStrategytype mismatch is valid, but its impact should be described precisely. A valid QPS parameter is converted toDouble; the mismatch appears when empty or malformed input leaves the integer default in place. HTTP and RPC initialization also appear to handle this failure differently, so both paths need tests. - The transaction diagnostic fix is straightforward. Please test that the exception contains the current transaction ID rather than the batch message ID.
- Reading
peekLast()once and null-checking it prevents the immediate NPE, but it does not provide a stable queue state. Please confirm whether snapshot semantics are sufficient or whether synchronization is required, and add a concurrency regression test. - Removing the throwable argument and changing the severity from
ERRORtoWARNare separate behavioral changes. The stack trace can be suppressed while retainingERROR; any severity downgrade should be justified independently.
These items affect unrelated subsystems, so this issue can remain the umbrella tracker, but the fixes should be submitted as separate PRs—or at minimum clearly separated commits—with focused tests and an explicit observable-behavior statement for each item. Once items 1 and 3 are clarified, the implementation can proceed item by item.
- For
@lxcmyf, these distinctions are valid. I will first tighten the issue description: item 1 does not yet establish a reachable case where an unsuccessful, non-cancelled
ChannelFuturehas a nullcause(), so I will describe the null handling as defensive hardening and ensure diagnostic logging cannot interrupt cleanup. For item 3, I will clarify that a valid QPS parameter is converted toDouble; the type mismatch occurs when empty or malformed input leaves the integer default in place. I will test the HTTP and RPC initialization paths separately.For implementation, item 2 will verify that HELLO validation precedes
updateNodeIdand other peer-state changes, with invalid and boundary-sized fields covered by tests. Item 4 will test that the exception contains the current transaction ID. For item 5, I will determine whether subsequent processing only needs the value read once or requires a stable queue state, then add a concurrency regression test and synchronize where needed. For item 6,BAD_MESSAGEis a recognized, handled P2P exception, so I will log it atWARNconsistently with other handled P2P exceptions and omit the full stack trace; unexpected or unhandled exceptions will remain atERROR. I will split the six items into focused PRs by subsystem, each stating its observable behavior and test results.Thanks, this plan addresses my concerns. Please update the issue description accordingly and link each focused PR back to this issue when it is opened, including its observable-behavior statement and test results.
@lxcmyf, I will update the issue description to reflect our discussion: clarify the reachability limitation for item 1, the conditions that trigger the type mismatch in item 3, and the rationale for logging handled P2P exceptions at
WARNin item 6. Each focused PR will link back to this issue and state its observable behavior and test results.These acceptance criteria look reasonable. I would make a few implementation details explicit:
Item 3: Empty input, missing
qps, and invalid values such asqps=abcorqps=0all reach the boxed-integer default; the invalid cases do so through the reset inparseStrategyParams(). HTTP currently fails initialization withTronError(RATE_LIMITER_INIT), following the fatal initialization policy introduced inc9b7fbc47e, while RPC retains theDefaultBaseQqsAdapterinstalled in its first initialization loop.Correcting the default type therefore changes these HTTP cases from startup failure to successful fallback. That behavior should be an explicit decision. The invalid-value cases already emit a generic parsing warning; empty or missing parameters may not. Please test the installed adapter and effective rate for valid, empty, missing, and invalid inputs, and distinguish unknown-adapter errors from construction failures in the RPC warning.
Item 2: Agreed on covering rejection-path logging. Currently, when
valid()returns false,processHelloMessage()disconnects and returns; it does not normally route that rejection throughprocessException(). The existing logging costs are the pre-validation INFO rendering and the full hash encoding in the validation-failure log."No full rendering of an invalid HELLO on any rejection path" would capture the intended behavior, including future error-routing changes. Validation should also precede
updateNodeId, with tests verifying that invalid messages do not reach that state update.Item 5: The remaining window is the tail-trimming loop in
ChainInventoryMsgHandler.processMessage(), before theblockLocksection. Concurrent removal inprocessSyncBlock(), or clearing instartSync()/PeerConnection.onDisconnect(), can invalidate the earlier nonempty observation. Commit8b4a5dddaddressed a differentpeek()/pop()sequence.Please use a deterministic interleaving test and assert correct trimming and block ordering around the common-block boundary. If locking is chosen, the relevant removal and clearing paths must participate in the same synchronization.
Item 6: The current behavior is
BAD_MESSAGE: ERROR with a throwable; otherP2pException: WARN without a throwable; non-P2pException: WARN with a throwable. Commitab07d2fe2bexplicitly changedBAD_MESSAGEfrom WARN to ERROR, so lowering it should have a stated rationale. Also, keeping unexpected exceptions at ERROR would actually require changing the current non-P2pExceptionbranch.Please specify the intended severity, throwable handling, and rendering bounds for all three branches, while preserving the existing disconnect behavior.
Agreed that item 1 remains defensive hardening and the transaction-ID correction can proceed independently.
Thanks for tracing the existing behavior and the relevant history. I agree that these details should become explicit acceptance criteria.
For item 3, correcting the boxed default type must not silently change the HTTP fatal-initialization policy as an unintended side effect. Whether invalid, empty, or missing QPS parameters should fail startup or fall back must be decided and tested explicitly for HTTP and RPC.
For item 6, suppressing the stack trace should be separated from changing the severity. Given that
BAD_MESSAGEwas deliberately changed toERRORbyab07d2fe2b, my preference is to retainERRORunless a separate operational rationale supports lowering it. The current non-P2pExceptionbranch should also be documented accurately and considered separately.@xxo1shine, please incorporate these clarifications—together with the deterministic interleaving requirement for item 5—into the issue description and the focused PR acceptance criteria before implementation.
@waynercheung, thank you for your comments. For item 2, invalid HELLO messages will not be fully rendered on any rejection path, and validation will occur before
updateNodeId. For item 3, the tests will cover valid, empty, missing, and invalid QPS parameters, and verify the adapter installed by HTTP/RPC and its effective rate so that correcting the type does not unintentionally change initialization behavior. For item 5, a deterministic interleaving test will cover the common-block boundary, and the relevant removal and clearing paths will use a consistent synchronization mechanism. For item 6, the severity, throwable handling, and rendering bounds will be defined separately for all three exception branches.BAD_MESSAGEis an expected remote protocol error and will be logged atWARNwithout a full stack trace; unexpected exceptions will be logged atERROR. The existing disconnect behavior will remain unchanged.@lxcmyf, thank you for the additional clarification. For item 3, the tests will cover valid, empty, missing, and invalid QPS parameters and verify the HTTP/RPC initialization result, installed adapter, and effective rate so that correcting the type does not unintentionally change the existing policy. For item 5, a deterministic interleaving test will cover queue trimming and block ordering around the common-block boundary. For item 6, the three exception branches will be handled separately.
BAD_MESSAGEis an expected remote protocol error for which the peer is already disconnected; logging it atERRORwith a full stack trace creates unnecessary operational noise, so it will be logged atWARNwithout the stack trace. Unexpected exceptions will be logged atERROR, while the existing disconnect behavior will remain unchanged.- added a parent issue
on Sep 17, 2026 - linked a pull request that will close this issuefix(net): robustness fixes for multiple issues #6983
on Sep 21, 2026
Metadata
Metadata
Assignees
Labels
Type
Projects
- StatusShow more project fieldsNo status
Summary
This issue consolidates six robustness problems:
EffectiveCheckServicedereferencesfuture.cause()without a null check, potentially interrupting subsequent cleanup.valid()validation.QpsStrategyhas a runtime type inconsistent with its declaredDouble.classtype, potentially causing aClassCastExceptionand configuration fallback.TransactionsMsgHandlerrecords the hash of the entire transaction message instead of the current transaction ID.isEmpty()/peekLast()operation onsyncBlockToFetchhas a concurrency window that may cause a null dereference.BAD_MESSAGE, while other handled P2P exceptions log only the exception message, resulting in inconsistent and unnecessarily verbose logging.Root Cause
1. Missing null check for the failure cause in
EffectiveCheckServiceIf
future.cause()is null in this branch, evaluatingfuture.cause().getMessage()throws an NPE. The subsequent operations that close the channel, resetcur, and advance peer selection are skipped.Actual reachability requires checking listener invocation timing, cancellation semantics, and other cleanup paths. The fact that the
cause()API permits null does not by itself establish that this state occurs in the failure callback.2. HELLO messages are logged before validation
P2pEventHandlerImpl.processMessage()logs messages before dispatching them:HELLO validation through
valid()occurs later, insidehandshakeService.processHelloMessage(). Consequently, peer-controlled fields that fail validation may already have been rendered bytoString()and written to logs, causing unnecessary formatting and logging overhead.3.
QpsStrategydefault parameter type mismatchThe default QPS value is stored as an
intin aParamItemdeclared asDouble.class. This creates a mismatch between the declared type and the actual boxed type,Integer.A subsequent direct cast to
Doublemay throwClassCastException. If the surrounding code catches the exception and falls back to a default strategy, custom endpoint rate-limit settings may not take effect as intended.4. The unrequested-transaction error uses the batch message ID
Here,
msgis aTransactionsMessage. ItsgetMessageId()returns the hash of the entire message payload rather than the ID of the current transaction in the loop. The current transaction ID is already available in the local variableid.5. A concurrency window exists between checking and reading
syncBlockToFetchCalling
isEmpty()and then dereferencing the result ofpeekLast()does not guarantee that the shared queue remains nonempty between those operations.If another thread clears the queue or removes its final element during that interval,
peekLast()may return null, causing an NPE.This is another instance of the access pattern addressed by fix
8b4a5dddf3, but this location appears not to have been covered. The specific remaining location should be checked against that fix during implementation.6. Inconsistent stack-trace logging for P2P exceptions
The
BAD_MESSAGEbranch passesexas the trailing throwable argument, causing the logger to print its full stack trace. Other P2P exception types log onlyex.getMessage(). Repeated malformed messages can therefore generate unnecessary stack-trace output.Impact
The current descriptions do not establish consensus divergence or financial impact.
Suggested Fix
Null-check
future.cause()and ensure that diagnostic logging failures cannot prevent necessary cleanup. Also check exception isolation between cleanup operations and whether repeated cleanup is safe.Validate HELLO fields before fully rendering the message, or log only a bounded summary.
Store the default QPS value as a
Double, keeping the declared, stored, and read types consistent. Log configuration parsing failures explicitly.Use the current transaction ID in the error message:
isEmpty()result:If subsequent operations require the queue state to remain unchanged, use a consistent synchronization mechanism as well.
BAD_MESSAGE: