{"record":{"id":"5d81654bab1b0945","repo":"zed-industries/zed","slug":"user-is-not-a-channel-member-or-channel-does-not-e","errorCode":null,"errorMessage":"user is not a channel member or channel does not exist","messagePattern":"user is not a channel member or channel does not exist","errorType":"validation","errorClass":"Error::Internal","httpStatus":null,"severity":"error","filePath":"crates/collab/src/db/queries/channels.rs","lineNumber":765,"sourceCode":"                \"user is not a channel admin or channel does not exist\"\n            ))?,\n        }\n    }\n\n    /// Returns whether the given user is a member of the specified channel.\n    pub async fn check_user_is_channel_member(\n        &self,\n        channel: &channel::Model,\n        user_id: UserId,\n        tx: &DatabaseTransaction,\n    ) -> Result<ChannelRole> {\n        let channel_role = self.channel_role_for_user(channel, user_id, tx).await?;\n        match channel_role {\n            Some(ChannelRole::Admin) | Some(ChannelRole::Member) => Ok(channel_role.unwrap()),\n            Some(ChannelRole::Banned)\n            | Some(ChannelRole::Guest)\n            | Some(ChannelRole::Talker)\n            | None => Err(anyhow!(\n                \"user is not a channel member or channel does not exist\"\n            ))?,\n        }\n    }\n\n    /// Returns whether the given user is a participant in the specified channel.\n    pub async fn check_user_is_channel_participant(\n        &self,\n        channel: &channel::Model,\n        user_id: UserId,\n        tx: &DatabaseTransaction,\n    ) -> Result<ChannelRole> {\n        let role = self.channel_role_for_user(channel, user_id, tx).await?;\n        match role {\n            Some(ChannelRole::Admin)\n            | Some(ChannelRole::Member)\n            | Some(ChannelRole::Guest)\n            | Some(ChannelRole::Talker) => Ok(role.unwrap()),","sourceCodeStart":747,"sourceCodeEnd":783,"githubUrl":"https://github.com/zed-industries/zed/blob/bc538def4545534201bbfcac4e95ac34ea6501b6/crates/collab/src/db/queries/channels.rs#L747-L783","documentation":"Thrown by check_user_is_channel_member (crates/collab/src/db/queries/channels.rs:765): the user's role is Banned, Guest, Talker, or None. Only Admin and Member count as full members; Talker/Guest are read-oriented roles and Banned users are excluded entirely.","triggerScenarios":"A Talker or Guest (e.g. a public-channel participant without membership) invoking member-gated operations; a banned user attempting any member action; a user with no channel_member row (None).","commonSituations":"Users who joined a public channel's call as guests assuming they became members; after a ban takes effect but the client session predates it; role changed to Talker to revoke write access, then member-only RPCs start failing.","solutions":["Have an admin upgrade the user's role to Member or Admin for that channel","Unban the user first if the role is Banned — unbanning must precede any member action","On the client, gate member-only actions on the precise role value, not on mere channel visibility"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"fn is_full_member(role: Option<ChannelRole>) -> bool {\n    matches!(role, Some(ChannelRole::Admin) | Some(ChannelRole::Member))\n}","typeGuard":"fn is_channel_member(role: Option<ChannelRole>) -> bool {\n    matches!(role, Some(ChannelRole::Admin) | Some(ChannelRole::Member))\n}","tryCatchPattern":null,"preventionTips":["Gate member-only actions on role being Admin or Member — Talker/Guest are read roles","After a ban or downgrade, expect in-flight member RPCs to fail; refresh roles from server events","Joining a public channel's call as guest does not confer membership"],"tags":["collab","channels","authorization","roles"],"backgroundTag":null,"analyzedSha":"bc538def4545534201bbfcac4e95ac34ea6501b6","analyzedAt":"2026-08-16T07:30:46.435Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}