zed-industries/zed · error

failed to ring user

Error message

failed to ring user

What it means

Terminal error from the call_user handler when every attempt to deliver the IncomingCall request to the called user's connections fails (FuturesUnordered of peer requests yields no Ok). Before returning, the handler compensates: it marks the call failed via call_failed, broadcasts room_updated, and updates contacts, so the room state is rolled back consistently. Empty connection sets also land here because there is nothing to succeed.

Source

Thrown at crates/collab/src/rpc.rs:1803

                return Ok(());
            }
            Err(_) => {
                call_response.trace_err();
            }
        }
    }

    {
        let room = session
            .db()
            .await
            .call_failed(room_id, called_user_id)
            .await?;
        room_updated(&room, &session.peer);
    }
    update_user_contacts(called_user_id, &session).await?;

    Err(anyhow!("failed to ring user"))?
}

/// Cancel an outgoing call.
async fn cancel_call(
    request: proto::CancelCall,
    response: Response<proto::CancelCall>,
    session: MessageContext,
) -> Result<()> {
    let called_user_id = UserId::from_proto(request.called_user_id);
    let room_id = RoomId::from_proto(request.room_id);
    {
        let room = session
            .db()
            .await
            .cancel_call(room_id, session.connection_id, called_user_id)
            .await?;
        room_updated(&room, &session.peer);
    }

View on GitHub (pinned to bc538def45)

Solutions

  1. Check the called user's online/presence state before placing the call and disable the button when offline
  2. Retry the call after a short delay — the user may have just come online; refresh presence between attempts
  3. Handle this error as 'unavailable' in the UI rather than a hard failure, since the room was already cleaned up

Example fix

// before
client.call_user(room_id, called_user_id, None).await?;

// after (presence gate + friendly failure)
if !presence.is_online(called_user_id) {
    self.ui.show_toast("User is offline");
    return Ok(());
}
if let Err(err) = client.call_user(room_id, called_user_id, None).await {
    if err.to_string().contains("failed to ring user") {
        self.ui.show_toast("Could not reach user; try again later");
        return Ok(());
    }
    return Err(err);
}
Defensive patterns

Strategy: retry

Validate before calling

// Presence gate before placing a call.
if !presence.is_online(called_user_id) {
    self.ui.show_toast("User is offline");
    return Ok(());
}
client.call_user(room_id, called_user_id, None).await?;

Try / catch

for attempt in 0..3 {
    match client.call_user(room_id, called_user_id, None).await {
        Ok(_) => return Ok(()),
        Err(err) if err.to_string().contains("failed to ring user") && attempt < 2 => {
            smol::Timer::after(Duration::from_secs(2)).await; // user may come online
        }
        Err(err) => {
            self.ui.show_toast("Could not reach user; try again later");
            return Ok(()); // room state was already rolled back server-side
        }
    }
}

Prevention

When it happens

Trigger: Called user is fully offline (no active connections); all their connections are on servers unreachable from this one; their clients reject/timeout the IncomingCall request; transient network partition during ring delivery.

Common situations: Calling someone whose app is closed; cross-server routing broken during departs; user signed out on all devices; mobile push-only users with no live socket.

Related errors


AI-assisted analysis of zed-industries/zed@bc538def45 (2026-08-16). Data as JSON: /api/errors/b4ed8d1f02aa2cd8. Report an issue: GitHub.