fix(sse): saturate exponential reconnect backoff #1198
Description
Problem
ExponentialBackoff::retry computes the reconnect multiplier as 2^current_times using u32::pow. With max_times unset, current_times can reach 32; in debug builds this overflows and panics, while release arithmetic can wrap and produce an incorrect delay. The resulting behavior makes a long-lived SSE client vulnerable to a retry-loop panic or unexpectedly short backoff.
Proposed direction
Saturate the multiplier at u32::MAX once current_times reaches the bit width, then use saturating multiplication for the base duration. This keeps the existing unbounded policy while making the delay monotonic and panic-free.
Verification
A focused regression at current_times = 32 reproduces the overflow on the pre-fix implementation and passes with the saturating calculation. The rmcp test suite and clippy checks pass on the proposed patch.
Would maintainers like this fix submitted as a PR?
Activity
acamarata commentedon Aug 25, 2026
I'd like to take this one.
The saturating approach you describe is the right call. Concretely, I'd clamp the shift once
current_timesreaches the bit width so the multiplier saturates atu32::MAXrather than wrapping, then usesaturating_mulon the base duration so the delay stays monotonic and the policy stays unbounded without ever panicking.For the regression I'd cover three points rather than just the overflow: the boundary at
current_times = 32, one value past it to confirm the delay stops growing instead of resetting, and a low value to confirm existing behavior is unchanged. The middle one is the case that actually distinguishes a saturating fix from a wrapping one.Will open a PR shortly unless someone is already on it.
fix(sse): default max_delay to None to preserve unbounded backoff
fix(sse): saturate exponential reconnect backoff to avoid overflow pa…