zed-industries/zed · warning

not in a call

Error message

not in a call

What it means

The collab ServerContext implementation for ActiveCall::join_project requires an active room; when the call entity has no room set (never joined, already left, or room creation still pending), the request is rejected with this error before touching the room.

Source

Thrown at crates/call/src/call_impl/mod.rs:205

    fn most_active_project(&self, cx: &App) -> Option<(u64, u64)> {
        let room = self.0.read(cx).room()?;
        room.read(cx).most_active_project(cx)
    }

    fn share_project(&self, project: Entity<Project>, cx: &mut App) -> Task<Result<u64>> {
        self.0
            .update(cx, |this, cx| this.share_project(project, cx))
    }

    fn join_project(
        &self,
        project_id: u64,
        language_registry: Arc<language::LanguageRegistry>,
        fs: Arc<dyn fs::Fs>,
        cx: &mut App,
    ) -> Task<Result<Entity<Project>>> {
        let Some(room) = self.0.read(cx).room().cloned() else {
            return Task::ready(Err(anyhow::anyhow!("not in a call")));
        };
        room.update(cx, |room, cx| {
            room.join_project(project_id, language_registry, fs, cx)
        })
    }

    fn peer_id_for_user_in_room(&self, user_id: u64, cx: &App) -> Option<proto::PeerId> {
        let room = self.0.read(cx).room()?.read(cx);
        room.remote_participants()
            .values()
            .find(|p| p.user.legacy_id == user_id)
            .map(|p| p.peer_id)
    }

    fn subscribe(
        &self,
        window: &mut Window,
        cx: &mut Context<Workspace>,

View on GitHub (pinned to bc538def45)

Solutions

  1. Treat it as a benign race in callers: check the call/room state before dispatching join_project.
  2. Re-join the call first, then retry the project join.
  3. If persistent, inspect the collab connection state (reconnect, re-auth) before retrying.

Example fix

// before: fire the request blindly
let task = call.join_project(project_id, registry, fs, cx);

// after: guard on room state first
if call.read(cx).room().is_none() {
    return Task::ready(Err(anyhow::anyhow!("not in a call")));
}
let task = call.join_project(project_id, registry, fs, cx);
Defensive patterns

Strategy: validation

Validate before calling

if call.read(cx).room().is_none() {
    // skip the request or re-join the call first, instead of firing join_project
    return Task::ready(Err(anyhow::anyhow!("not in a call")));
}
let task = call.join_project(project_id, language_registry, fs, cx);

Type guard

fn is_in_call(call: &Entity<ActiveCall>, cx: &App) -> bool {
    call.read(cx).room().is_some()
}

Try / catch

treat Err("not in a call") from join_project as a benign race: drop the pending request and refresh call state instead of surfacing a hard error to the user.

Prevention

When it happens

Trigger: A join-project RPC arrives while self.0.read(cx).room() is None - the user hung up just before the request, room creation has not finished, or the room was torn down after a disconnect.

Common situations: Races between leave_call/hang-up and in-flight join-project requests; clicking a shared-project action during reconnect; clients that keep sending requests after the room ended.

Related errors


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