n0-computer/iroh · warning
The relay is rate-limiting this endpoint; outbound relay…
Error message
The relay is rate-limiting this endpoint; outbound relay traffic is being throttled. Send less data over the relay, or, if you operate this relay, raise Limits::client_rx. Read more about rate limiting at https://docs.iroh.computer/relays/rate-limiting
What it means
This is a relay health-status error from iroh-relay. The relay server is throttling traffic received from this client endpoint because it exceeded the configured receive limits (Limits::client_rx). Once throttling starts, data sent through the relay is delayed/dropped, so outbound relay traffic toward peers slows down.
Solutions
- Reduce the volume/frequency of data sent over the relay; prefer direct (holepunched) connections so traffic bypasses the relay.
- If you operate the relay, raise the client_rx limit in the relay's Limits configuration.
- Check relay connectivity/latency and whether direct connection establishment is failing, forcing all traffic through the relay.
- Back off and retry after throttling; the status is sent once per connection when throttling first begins.
Example fix
// before: relay operator with default limits
let server = RelayServer::builder().bind(0.0.0.0:3340).await?;
// after: raise per-client receive limit
let server = RelayServer::builder()
.bind(0.0.0.0:3340).await?
.client_rx(10_000_000) // bytes/sec, raised from default
.spawn(); Defensive patterns
Strategy: retry
Validate before calling
// No pre-call check possible; monitor client health statuses instead.
fn handle_health(status: &ClientHealth) {
if matches!(status, ClientHealth::RateLimited) {
// enable backpressure: queue relayed sends, prefer direct connections
}
} Type guard
fn is_rate_limited(h: &ClientHealth) -> bool { matches!(h, ClientHealth::RateLimited) } Try / catch
match result {
Ok(v) => v,
Err(e) if is_rate_limited_msg(&e) => schedule_backoff_and_retry(),
Err(e) => return Err(e),
} Prevention
- Prefer direct (holepunched) connections over relayed traffic
- Add client-side send throttling/queueing for relayed data
- If you run the relay, size Limits::client_rx to expected per-client throughput
- Watch relay health statuses and back off at the first RateLimited signal
When it happens
Trigger: A client connected to an iroh relay sends data faster than the relay's client_rx rate limit allows. The relay emits this ClientHealth::RateLimited status once per connection when it first begins throttling reads from that client.
Common situations: Chatty applications that push large amounts of relayed (non-direct) traffic; many endpoints sharing one relay with per-client limits; operators who set Limits::client_rx too low for their workload; dev/test setups where heavy traffic intentionally flows over the relay instead of via direct connections.
Related errors
- Invalid transport configuration
- UnexpectedUpgradeStatus
- ExceedsMaxPacketSize
- EmptyPacket
- ExceedsMaxPacketSize
AI-assisted analysis of n0-computer/iroh@2b4de030ce (2026-09-08).
Data as JSON: /api/errors/c7a082ec1bd6fc6a.
Report an issue: GitHub.
Appendix: source
Thrown at iroh-relay/src/protos/relay.rs:136
/// One-way message from server to client indicating issues with the relay connection.
#[derive(Debug, Clone, PartialEq, Eq, derive_more::Display)]
#[non_exhaustive]
pub enum Status {
/// The connection is healthy and recovered from previous problems.
#[display("The connection is healthy and has recovered from previous problems")]
Healthy,
/// Another endpoint connected with the same endpoint id. No more messages will be received.
#[display(
"Another endpoint connected with the same endpoint id. No more messages will be received."
)]
SameEndpointIdConnected,
/// The relay is rate-limiting traffic received from this endpoint.
///
/// Sent once per connection when the relay first throttles reading from the client.
#[display(
"The relay is rate-limiting this endpoint; outbound relay traffic is being throttled. \
Send less data over the relay, or, if you operate this relay, raise Limits::client_rx. \
Read more about rate limiting at https://docs.iroh.computer/relays/rate-limiting"
)]
RateLimited,
/// Placeholder for backwards-compatibility for future new health status variants.
#[display("Unsupported health message ({_0})")]
Unknown(u8),
}
impl Status {
#[cfg(feature = "server")]
fn write_to<O: BufMut>(&self, mut dst: O) -> O {
match self {
Status::Healthy => dst.put_u8(0),
Status::SameEndpointIdConnected => dst.put_u8(1),
Status::RateLimited => dst.put_u8(2),
Status::Unknown(discriminant) => dst.put_u8(*discriminant),
}
dstView on GitHub (pinned to 2b4de030ce)