{"record":{"id":"ae416b2b37bc2f20","repo":"zed-industries/zed","slug":"guests-cannot-share-projects","errorCode":null,"errorMessage":"guests cannot share projects","messagePattern":"guests cannot share projects","errorType":"validation","errorClass":"Error::Internal","httpStatus":null,"severity":"error","filePath":"crates/collab/src/db/queries/projects.rs","lineNumber":63,"sourceCode":"                                .eq(connection.id as i32),\n                        )\n                        .add(\n                            room_participant::Column::AnsweringConnectionServerId\n                                .eq(connection.owner_id as i32),\n                        ),\n                )\n                .one(&*tx)\n                .await?\n                .context(\"could not find participant\")?;\n            if participant.room_id != room_id {\n                return Err(anyhow!(\"shared project on unexpected room\"))?;\n            }\n            if !participant\n                .role\n                .unwrap_or(ChannelRole::Member)\n                .can_edit_projects()\n            {\n                return Err(anyhow!(\"guests cannot share projects\"))?;\n            }\n\n            let project = project::ActiveModel {\n                room_id: ActiveValue::set(Some(participant.room_id)),\n                host_user_id: ActiveValue::set(Some(participant.user_id)),\n                host_connection_id: ActiveValue::set(Some(connection.id as i32)),\n                host_connection_server_id: ActiveValue::set(Some(ServerId(\n                    connection.owner_id as i32,\n                ))),\n                id: ActiveValue::NotSet,\n                windows_paths: ActiveValue::set(windows_paths),\n                features: ActiveValue::set(serde_json::to_string(features).unwrap()),\n            }\n            .insert(&*tx)\n            .await?;\n\n            if !worktrees.is_empty() {\n                worktree::Entity::insert_many(worktrees.iter().map(|worktree| {","sourceCodeStart":45,"sourceCodeEnd":81,"githubUrl":"https://github.com/zed-industries/zed/blob/bc538def4545534201bbfcac4e95ac34ea6501b6/crates/collab/src/db/queries/projects.rs#L45-L81","documentation":"Thrown by share_project (crates/collab/src/db/queries/projects.rs:63): the calling connection's room participant role fails can_edit_projects(), which per crates/collab/src/db/ids.rs:213-219 is true only for Admin and Member — Talker, Guest and Banned are rejected. Sharing a project into a room requires full membership; the error message names the common case (guests).","triggerScenarios":"A user whose room_participant.role is Talker or Guest calling share_project for that room (e.g. joined a public channel call as a guest and then tries to share a project); a user with role NULL is defaulted to Member at projects.rs:60 and passes, so the failure specifically requires an explicit non-editing role.","commonSituations":"Guests in public channels attempting screen/project share with a member-only feature set; after an admin downgrades a noisy user to Talker, their active share attempts start failing; clients not hiding the 'Share project' action for talker/guest roles.","solutions":["Have a channel admin promote the user to Member (or Admin) for the channel that owns the room, then retry the share","Gate the share-project UI on the participant role: hide it when !role.can_edit_projects()","Note the neighboring check: the connection must also be a participant of that exact room (participant.room_id == room_id), so ensure the connection is the one that joined the call"],"exampleFix":"// before\nclient.share_project(room_id, connection_id, worktrees, ..).await?; // guest\n\n// after\nlet role = participant.role.unwrap_or(ChannelRole::Member);\nif !role.can_edit_projects() {\n    return Err(anyhow!(\"ask an admin to promote you to member before sharing\"));\n}\nclient.share_project(room_id, connection_id, worktrees, ..).await?;","handlingStrategy":"validation","validationCode":"// Mirror the server rule before sharing\nlet role = participant.role.unwrap_or(ChannelRole::Member);\nif !role.can_edit_projects() {\n    return Err(anyhow!(\"role cannot share projects; need member or admin\"));\n}","typeGuard":"fn can_share_projects(role: Option<ChannelRole>) -> bool {\n    role.unwrap_or(ChannelRole::Member).can_edit_projects()\n}","tryCatchPattern":"match db.share_project(room_id, connection, worktrees, ..).await {\n    Ok(v) => Ok(v),\n    Err(err) if err.to_string().contains(\"guests cannot share projects\") => {\n        Err(anyhow!(\"ask an admin to promote you to member to share projects\"))\n    }\n    Err(err) => Err(err),\n}","preventionTips":["Hide share-project UI for Talker/Guest participants in rooms","The sharing connection must itself be a participant of that exact room (same connection that joined the call)","After role downgrades, expect in-flight share attempts to fail; gate on fresh role state"],"tags":["collab","projects","rooms","authorization","roles"],"backgroundTag":null,"analyzedSha":"bc538def4545534201bbfcac4e95ac34ea6501b6","analyzedAt":"2026-08-16T07:30:46.435Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}