zed-industries/zed · error
could not update room participant role
Error message
could not update room participant role
What it means
Thrown by set_room_participant_role when the UPDATE of role on the (room_id, user_id) participant row does not affect exactly 1 row. The target user must currently be a participant of the room; zero affected rows means they left, were kicked, or never joined.
Source
Thrown at crates/collab/src/db/queries/rooms.rs:1164
self.check_user_has_signed_cla(user_id, room_id, &tx)
.await?;
}
let result = room_participant::Entity::update_many()
.filter(
Condition::all()
.add(room_participant::Column::RoomId.eq(room_id))
.add(room_participant::Column::UserId.eq(user_id)),
)
.set(room_participant::ActiveModel {
role: ActiveValue::set(Some(role)),
..Default::default()
})
.exec(&*tx)
.await?;
if result.rows_affected != 1 {
Err(anyhow!("could not update room participant role"))?;
}
self.get_room(room_id, &tx).await
})
.await
}
async fn check_user_has_signed_cla(
&self,
user_id: UserId,
room_id: RoomId,
tx: &DatabaseTransaction,
) -> Result<()> {
let channel = room::Entity::find_by_id(room_id)
.one(tx)
.await?
.context("could not find room")?
.find_related(channel::Entity)
.one(tx)View on GitHub (pinned to bc538def45)
Solutions
- Refresh the room's participant list immediately before issuing the role change and target only users still present
- Treat this error as 'user no longer in room' and update the admin UI accordingly
- If the intent is to pre-assign a role, invite the user (or have them rejoin) and then set the role
Example fix
// before
client.set_room_participant_role(room_id, target_user_id, new_role).await?;
// after (check membership first)
let room = client.get_room(room_id).await?;
let is_present = room.participants.iter().any(|p| p.user_id == target_user_id);
if !is_present {
log::warn!("user {target_user_id} is no longer in room {room_id}; skipping role change");
return Ok(());
}
client.set_room_participant_role(room_id, target_user_id, new_role).await?; Defensive patterns
Strategy: validation
Validate before calling
// Verify the target is still present before changing their role.
let room = client.get_room(room_id).await?;
if !room.participants.iter().any(|p| p.user_id == target_user_id) {
log::warn!("target {target_user_id} not in room {room_id}; skipping role change");
return Ok(());
}
client.set_room_participant_role(room_id, target_user_id, role).await?; Type guard
fn is_room_participant(room: &proto::Room, user_id: u64) -> bool {
room.participants.iter().any(|p| p.user_id == user_id)
} Try / catch
match client.set_room_participant_role(room_id, target_user_id, role).await {
Ok(room) => Ok(room),
Err(err) if err.to_string().contains("could not update room participant role") => {
self.refresh_participants(room_id); // target left; resync UI
Ok(None)
}
Err(err) => Err(err),
} Prevention
- Refresh the participant list immediately before admin role actions
- Design admin UI so actions on departed users are no-ops, not errors
- Handle kick/leave events by removing users from pending moderation queues
When it happens
Trigger: Admin calls SetRoomParticipantRole for a user who just left the room or disconnected and was cleaned up; role change targeting a user_id that was never in the room; concurrent kick and role change racing so the row is deleted first.
Common situations: Admin UI acting on a stale participant list; moderation actions queued while the target user signs off; race between connection-loss cleanup and an admin's command.
Related errors
- could not find call to decline
- room does not exist or was already joined
- could not update room participant location
- guests cannot share projects
- not authorized to edit projects
AI-assisted analysis of zed-industries/zed@bc538def45 (2026-08-16).
Data as JSON: /api/errors/be63a705e54d3c96.
Report an issue: GitHub.