zed-industries/zed · error · Error::Internal

not authorized to read projects

Error message

not authorized to read projects

What it means

Thrown during project join authorization when the requested capability is Capability::ReadOnly and the caller's channel role cannot even read projects (role.can_read_projects() is false). Banned is the only role that fails this check, and it is also the default when the caller has no room_participant row at all, so this usually means the user is not in the room where the project is shared.

Source

Thrown at crates/collab/src/db/queries/projects.rs:1142

                .filter(room_participant::Column::AnsweringConnectionId.eq(connection_id.id))
                .one(tx)
                .await?
                .and_then(|participant| participant.role)
        } else {
            None
        };

        let role = role_from_room.unwrap_or(ChannelRole::Banned);

        match capability {
            Capability::ReadWrite => {
                if !role.can_edit_projects() {
                    return Err(anyhow!("not authorized to edit projects"))?;
                }
            }
            Capability::ReadOnly => {
                if !role.can_read_projects() {
                    return Err(anyhow!("not authorized to read projects"))?;
                }
            }
        }

        Ok((project, role))
    }

    /// Returns the host connection for a read-only request to join a shared project.
    pub async fn host_for_read_only_project_request(
        &self,
        project_id: ProjectId,
        connection_id: ConnectionId,
    ) -> Result<ConnectionId> {
        self.project_transaction(project_id, |tx| async move {
            let (project, _) = self
                .access_project(project_id, connection_id, Capability::ReadOnly, &tx)
                .await?;
            project.host_connection()

View on GitHub (pinned to bc538def45)

Solutions

  1. Join the containing room (accept the invitation / call) before issuing JoinProject for the shared project
  2. Ask a room Admin to lift the ban on the caller's user
  3. Re-request an invitation to the room and then retry the project join

Example fix

// before
let joined = client.join_project(project_id, read_only).await?;

// after (join room first)
client.join_room(room_id).await?; // ensures a participant row with a valid role
let joined = client.join_project(project_id, read_only).await?;
Defensive patterns

Strategy: validation

Validate before calling

// Join the room before joining a project shared within it.
if !self.joined_rooms.contains(&room_id) {
    client.join_room(room_id, my_connection_id).await?;
}
client.join_project(project_id, capability).await?;

Try / catch

match client.join_project(project_id, false).await {
    Ok(joined) => Ok(joined),
    Err(err) if err.to_string().contains("not authorized to read projects") => {
        self.ui.show_toast("Join the room or ask to be unbanned first");
        Ok(default_join()) // or return a typed 'Unauthorized' to the caller
    }
    Err(err) => Err(err),
}

Prevention

When it happens

Trigger: JoinProject for a project shared in a room the caller never joined; the caller was banned from the room; the caller's participant row was deleted (kicked) before the join arrived.

Common situations: Joining a project by URL or ID without first accepting the room invitation; being kicked from a room while the project link is still open; clients that skip the room-join step of the share flow.

Related errors


AI-assisted analysis of zed-industries/zed@bc538def45 (2026-08-16). Data as JSON: /api/errors/3190c4802c9f7737. Report an issue: GitHub.