{"record":{"id":"1a773222c95e61be","repo":"zed-industries/zed","slug":"can-t-delete-channel-while-a-call-is-in-progress","errorCode":null,"errorMessage":"can't delete channel while a call is in progress","messagePattern":"can't delete channel while a call is in progress","errorType":"validation","errorClass":"Error::Internal","httpStatus":null,"severity":"error","filePath":"crates/collab/src/db/queries/channels.rs","lineNumber":272,"sourceCode":"                .await?;\n\n            let channels_to_remove = self\n                .get_channel_descendants_excluding_self([&channel], &tx)\n                .await?\n                .into_iter()\n                .map(|channel| channel.id)\n                .chain(Some(channel_id))\n                .collect::<Vec<_>>();\n\n            let channel_has_active_participants = room_participant::Entity::find()\n                .inner_join(room::Entity)\n                .filter(room::Column::ChannelId.is_in(channels_to_remove.iter().copied()))\n                .count(&*tx)\n                .await?\n                > 0;\n\n            if channel_has_active_participants {\n                Err(anyhow!(\"can't delete channel while a call is in progress\"))?;\n            }\n\n            channel::Entity::delete_many()\n                .filter(channel::Column::Id.is_in(channels_to_remove.iter().copied()))\n                .exec(&*tx)\n                .await?;\n\n            Ok((channel.root_id(), channels_to_remove))\n        })\n        .await\n    }\n\n    /// Invites a user to a channel as a member.\n    pub async fn invite_channel_member(\n        &self,\n        channel_id: ChannelId,\n        invitee_id: UserId,\n        inviter_id: UserId,","sourceCodeStart":254,"sourceCodeEnd":290,"githubUrl":"https://github.com/zed-industries/zed/blob/bc538def4545534201bbfcac4e95ac34ea6501b6/crates/collab/src/db/queries/channels.rs#L254-L290","documentation":"Thrown by delete_channel when any room under the channel (or any of its descendant channels collected into channels_to_remove) still has rows in room_participant (crates/collab/src/db/queries/channels.rs:263-272). The count query inner-joins room on ChannelId, so a single active participant anywhere in the subtree blocks the whole deletion inside the transaction.","triggerScenarios":"Calling delete_channel (admin RPC) while one or more users are in a call room belonging to the channel or any of its child channels; a crashed client whose room_participant row was never cleaned up on disconnect.","commonSituations":"Admin deletes a busy channel during a scheduled cleanup; leftover room_participant rows from a server that missed a leave event; CI/integration tests deleting fixture channels without first closing the call rooms.","solutions":["Have all participants leave the call (or kick them) so room_participant rows for those rooms are deleted, then retry the channel deletion","Check for orphaned room_participant rows (participants whose connection is gone) and clean them up before retrying","If deleting a channel tree, ensure no child channel's room has participants either — the check covers the whole channels_to_remove set"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Before delete_channel: confirm no room under the subtree has participants\nlet busy = rooms_under_channel_subtree\n    .iter()\n    .any(|room| room.active_participants > 0);\nif busy {\n    return Err(anyhow!(\"ask participants to leave the call before deleting\"));\n}","typeGuard":null,"tryCatchPattern":"match db.delete_channel(channel_id, admin_id).await {\n    Ok(result) => Ok(result),\n    Err(err) if err.to_string().contains(\"call is in progress\") => {\n        // surface an actionable 'participants still in call' message to the admin UI\n        Err(anyhow!(\"channel busy: a call is still in progress\"))\n    }\n    Err(err) => Err(err),\n}","preventionTips":["Check for active room participants before offering channel deletion in admin UIs","Kick remaining participants (or wait for their disconnect cleanup) before deleting","Monitor for orphaned room_participant rows from crashed clients and reap them"],"tags":["collab","channels","calls","database"],"backgroundTag":null,"analyzedSha":"bc538def4545534201bbfcac4e95ac34ea6501b6","analyzedAt":"2026-08-16T07:30:46.435Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}