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
- Treat it as a benign race in callers: check the call/room state before dispatching join_project.
- Re-join the call first, then retry the project join.
- 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
- Re-check room state after async boundaries before sending room-scoped RPCs
- Debounce join actions during hang-up/reconnect
- Reconcile UI from the error response rather than assuming success
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
- user was already invited
- {err:?}
- no such invitation
- HTTP error! status: ${response.status}
- Context server not initialized
AI-assisted analysis of zed-industries/zed@bc538def45 (2026-08-16).
Data as JSON: /api/errors/66064b7d9f93a482.
Report an issue: GitHub.