zed-industries/zed · error · Error::Internal
user is not a channel admin or channel does not exist
Error message
user is not a channel admin or channel does not exist
What it means
Thrown by check_user_is_channel_admin (crates/collab/src/db/queries/channels.rs:746): the user's ChannelRole resolved via channel_role_for_user is Member, Talker, Guest, Banned, or None (no membership row) — only Admin passes. Guards every admin-only operation (rename, delete, move, role changes).
Source
Thrown at crates/collab/src/db/queries/channels.rs:746
})
.await
}
/// Returns whether the given user is an admin in the specified channel.
pub async fn check_user_is_channel_admin(
&self,
channel: &channel::Model,
user_id: UserId,
tx: &DatabaseTransaction,
) -> Result<ChannelRole> {
let role = self.channel_role_for_user(channel, user_id, tx).await?;
match role {
Some(ChannelRole::Admin) => Ok(role.unwrap()),
Some(ChannelRole::Member)
| Some(ChannelRole::Talker)
| Some(ChannelRole::Banned)
| Some(ChannelRole::Guest)
| None => Err(anyhow!(
"user is not a channel admin or channel does not exist"
))?,
}
}
/// Returns whether the given user is a member of the specified channel.
pub async fn check_user_is_channel_member(
&self,
channel: &channel::Model,
user_id: UserId,
tx: &DatabaseTransaction,
) -> Result<ChannelRole> {
let channel_role = self.channel_role_for_user(channel, user_id, tx).await?;
match channel_role {
Some(ChannelRole::Admin) | Some(ChannelRole::Member) => Ok(channel_role.unwrap()),
Some(ChannelRole::Banned)
| Some(ChannelRole::Guest)
| Some(ChannelRole::Talker)View on GitHub (pinned to bc538def45)
Solutions
- Promote the user to ChannelRole::Admin for that channel before retrying (an existing admin must change the role)
- Ensure the client disables/hides admin actions based on the role delivered in membership_update events, and re-checks on role change
- Confirm you are passing the acting user's id (admin_id) and not the target's id — a swapped argument produces exactly this error
Defensive patterns
Strategy: validation
Validate before calling
// Client-side gate for admin actions
fn can_admin(role: Option<ChannelRole>) -> bool {
matches!(role, Some(ChannelRole::Admin))
}
if !can_admin(my_role) {
return Err(anyhow!("admin role required"));
} Type guard
fn is_channel_admin(role: Option<ChannelRole>) -> bool {
role == Some(ChannelRole::Admin)
} Try / catch
match db.delete_channel(channel_id, admin_id).await {
Ok(v) => Ok(v),
Err(err) if err.to_string().contains("not a channel admin") => {
Err(anyhow!("ask a channel admin to perform this action"))
}
Err(err) => Err(err),
} Prevention
- Hide rename/delete/move/role-change UI unless the user's role for that channel is Admin
- Update cached roles on every membership_update event
- Remember server-level admin and channel Admin are different — only the latter passes this check
When it happens
Trigger: A non-admin member/guest/talker/banned user calling delete_channel, rename_channel, move_channel, or remove_channel_member; calling any of these after the user's admin role was downgraded; calling with a user id that has no channel_member row at all (None arm).
Common situations: Role downgraded while the client kept an admin UI visible; a guest granted Talker expecting admin rights; org admins (server-level) assuming channel-admin powers — server admin is a different flag and does not pass this check.
Related errors
- user is not a channel member or channel does not exist
- user is not a channel participant or channel does not exist
- guests cannot share projects
- not authorized to edit projects
- not authorized to read projects
AI-assisted analysis of zed-industries/zed@bc538def45 (2026-08-16).
Data as JSON: /api/errors/f7de1fdcd921e473.
Report an issue: GitHub.