{"record":{"id":"5fd0485f5a456fa3","repo":"zed-industries/zed","slug":"no-such-member","errorCode":null,"errorMessage":"no such member","messagePattern":"no such member","errorType":"validation","errorClass":"Error::Internal","httpStatus":null,"severity":"error","filePath":"crates/collab/src/db/queries/channels.rs","lineNumber":490,"sourceCode":"        self.transaction(|tx| async move {\n            let channel = self.get_channel_internal(channel_id, &tx).await?;\n\n            if member_id != admin_id {\n                self.check_user_is_channel_admin(&channel, admin_id, &tx)\n                    .await?;\n            }\n\n            let result = channel_member::Entity::delete_many()\n                .filter(\n                    channel_member::Column::ChannelId\n                        .eq(channel_id)\n                        .and(channel_member::Column::UserId.eq(member_id)),\n                )\n                .exec(&*tx)\n                .await?;\n\n            if result.rows_affected == 0 {\n                Err(anyhow!(\"no such member\"))?;\n            }\n\n            Ok(RemoveChannelMemberResult {\n                membership_update: self\n                    .calculate_membership_updated(&channel, member_id, &tx)\n                    .await?,\n                notification_id: self\n                    .remove_notification(\n                        member_id,\n                        rpc::Notification::ChannelInvitation {\n                            channel_id: channel_id.to_proto(),\n                            channel_name: Default::default(),\n                            inviter_id: Default::default(),\n                        },\n                        &tx,\n                    )\n                    .await?,\n            })","sourceCodeStart":472,"sourceCodeEnd":508,"githubUrl":"https://github.com/zed-industries/zed/blob/bc538def4545534201bbfcac4e95ac34ea6501b6/crates/collab/src/db/queries/channels.rs#L472-L508","documentation":"Thrown by remove_channel_member (crates/collab/src/db/queries/channels.rs:490) when the DELETE of the channel_member row for (channel_id, member_id) affects 0 rows — the target user has no membership row in that channel, whether never a member or already removed.","triggerScenarios":"Admin calls remove-member for a user who already left the channel; removing a user whose invitation was revoked (pending row deleted); two admins racing to kick the same member; client UI showing a stale member list.","commonSituations":"Stale channel roster in the client after a membership_update event was dropped; kick + auto-leave racing; retry of a remove that already succeeded.","solutions":["Refresh the member list from the latest membership_update notification before offering the remove action","Treat the error as benign when the member is already gone (idempotent removal) and drop the notification cleanup accordingly","Verify the member_id being sent is the one from the roster entry, not a user id from another context"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Verify membership before issuing the kick\nif channel_members.contains_key(&member_id) {\n    db.remove_channel_member(channel_id, member_id, admin_id).await?;\n}","typeGuard":null,"tryCatchPattern":"// Kicking an already-gone member is a no-op\nmatch db.remove_channel_member(channel_id, member_id, admin_id).await {\n    Ok(result) => Ok(Some(result)),\n    Err(err) if err.to_string().contains(\"no such member\") => Ok(None),\n    Err(err) => Err(err),\n}","preventionTips":["Render admin kick actions from the latest membership_update, not a cached roster","Coordinate concurrent admins: expect one of two racing kicks to see 'no such member'","Include member ids (not display names) in remove requests to avoid mismatches"],"tags":["collab","channels","members","idempotency"],"backgroundTag":null,"analyzedSha":"bc538def4545534201bbfcac4e95ac34ea6501b6","analyzedAt":"2026-08-16T07:30:46.435Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}