nautechsystems/nautilus_trader · error · TransportError::Io(std::io::Error)
{field} exceeds the maximum backoff duration
Error message
{field} exceeds the maximum backoff duration What it means
Retry backoff durations are converted to milliseconds (u64) for scheduling. If the duration's nanosecond value overflows `u64::MAX` (about 584 years), `duration_to_millis` rejects it with `InvalidInput`, naming the offending field, because such a duration cannot be represented for the timer.
Source
Thrown at crates/network/src/websocket/client.rs:963
})
} else {
Ok(RetryConfig {
max_retries: 0,
initial_delay_ms: 1,
max_delay_ms: 1,
backoff_factor: 1.0,
jitter_ms: 0,
operation_timeout_ms: None,
immediate_first: false,
max_elapsed_ms: None,
})
}
}
fn duration_to_millis(field: &str, duration: Duration) -> Result<u64, TransportError> {
let nanoseconds = duration.as_nanos();
if nanoseconds > u128::from(u64::MAX) {
return Err(TransportError::Io(std::io::Error::new(
std::io::ErrorKind::InvalidInput,
format!("{field} exceeds the maximum backoff duration"),
)));
}
let milliseconds = nanoseconds
.div_ceil(1_000_000)
.min(u128::from(u64::MAX / 1_000_000));
u64::try_from(milliseconds).map_err(|_| {
TransportError::Io(std::io::Error::new(
std::io::ErrorKind::InvalidInput,
format!("{field} exceeds the maximum backoff duration"),
))
})
}
async fn await_initial_connect_attempt<F, T>(
cancellation_token: &CancellationToken,View on GitHub (pinned to 18893faf8b)
Solutions
- Cap the backoff field to a sane maximum (e.g. `Duration::from_secs(3600)`).
- Audit the arithmetic that produces the duration for overflow or wrong units.
- Clamp before constructing RetryConfig, mirroring the library's `min(u64::MAX / 1_000_000)` ms bound.
Example fix
// before let backoff = Duration::from_secs(initial).checked_mul(2u32.pow(n))?; // after let backoff = Duration::from_secs(initial).checked_mul(2u32.pow(n))?.min(Duration::from_secs(3600));
Defensive patterns
Strategy: validation
Validate before calling
fn cap_backoff(d: Duration, max: Duration) -> Duration {
if d > max { max } else { d }
}
let retry = RetryConfig { max_backoff: cap_backoff(computed, Duration::from_secs(3600)), .. }; Try / catch
match RetryConfig::new(initial, factor, max_backoff) {
Err(e) if e.to_string().contains("exceeds the maximum backoff duration") => {
eprintln!("backoff duration overflow; capping to 1h");
RetryConfig::new(initial, factor, Duration::from_secs(3600))?
}
other => other?,
} Prevention
- Always cap exponential backoff growth with a maximum duration.
- Check units when converting config numbers into Durations.
- Use checked arithmetic (checked_mul) when scaling durations.
When it happens
Trigger: Constructing `RetryConfig` with a backoff field (e.g. `max_backoff`/initial backoff) computed to an astronomically large `Duration` — typically from a bad multiplication, a u128/u64 mixup, or a parsed value without bounds.
Common situations: Programmatic backoff generation (exponential growth without cap) or deserializing durations from configs with absurd numeric values.
Understand the failure class
Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.
Related errors
- `durations_seconds` value is too large, was {value}
- DurationNanos overflow in from_micros
- {e}
- `durations_seconds` request parameter must contain non-negat
- `durations_seconds` request parameter must contain values of
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/252ee441be4754ed.
Report an issue: GitHub.