{"record":{"id":"7ce2bbe84b6401b5","repo":"zed-industries/zed","slug":"wrongmovetarget","errorCode":"WrongMoveTarget","errorMessage":"WrongMoveTarget","messagePattern":"WrongMoveTarget","errorType":"error_code","errorClass":"RpcError","httpStatus":null,"severity":"error","filePath":"crates/collab/src/db/queries/channels.rs","lineNumber":923,"sourceCode":"\n        Ok(room_id)\n    }\n\n    /// Move a channel from one parent to another\n    pub async fn move_channel(\n        &self,\n        channel_id: ChannelId,\n        new_parent_id: ChannelId,\n        admin_id: UserId,\n    ) -> Result<(ChannelId, Vec<Channel>)> {\n        self.transaction(|tx| async move {\n            let channel = self.get_channel_internal(channel_id, &tx).await?;\n            self.check_user_is_channel_admin(&channel, admin_id, &tx)\n                .await?;\n            let new_parent = self.get_channel_internal(new_parent_id, &tx).await?;\n\n            if new_parent.root_id() != channel.root_id() {\n                Err(anyhow!(ErrorCode::WrongMoveTarget))?;\n            }\n\n            if new_parent\n                .ancestors_including_self()\n                .any(|id| id == channel.id)\n            {\n                Err(anyhow!(ErrorCode::CircularNesting))?;\n            }\n\n            if channel.visibility == ChannelVisibility::Public\n                && new_parent.visibility != ChannelVisibility::Public\n            {\n                Err(anyhow!(ErrorCode::BadPublicNesting))?;\n            }\n\n            let root_id = channel.root_id();\n            let new_parent_path = new_parent.path();\n            let old_path = format!(\"{}{}/\", channel.parent_path, channel.id);","sourceCodeStart":905,"sourceCodeEnd":941,"githubUrl":"https://github.com/zed-industries/zed/blob/bc538def4545534201bbfcac4e95ac34ea6501b6/crates/collab/src/db/queries/channels.rs#L905-L941","documentation":"ErrorCode::WrongMoveTarget from move_channel (crates/collab/src/db/queries/channels.rs:923): the proposed new parent channel's root_id() differs from the moved channel's root_id(). Channels form trees per root (shared workspace); moving a channel across root trees is structurally illegal, so the move is rejected before path rewriting.","triggerScenarios":"Calling move_channel(channel_id, new_parent_id, admin_id) where new_parent lives in a different root channel — e.g. dragging a channel from one shared workspace tree into another organization's channel tree.","commonSituations":"UI drag-and-drop between top-level workspaces; client holding stale channel data after a channel was itself moved into another tree, so the cached parent path no longer matches the server's root computation.","solutions":["Choose a new parent within the same root tree (verify both channels' root_id() match client-side before issuing the move)","Refresh the channel tree from the server before offering move targets, so cross-root targets are not shown","If the channel genuinely must live in the other tree, create it there and move content instead — there is no supported cross-root move"],"exampleFix":"// before\nclient.move_channel(channel_id, other_root_child_id, admin_id).await?;\n\n// after\nassert_eq!(channel.root_id(), new_parent.root_id(), \"cross-root move\");\nclient.move_channel(channel_id, new_parent_id, admin_id).await?;","handlingStrategy":"validation","validationCode":"// Reject cross-root moves before sending\nif channel.root_id() != new_parent.root_id() {\n    return Err(anyhow!(\"can only move within the same root channel\"));\n}\ndb.move_channel(channel_id, new_parent_id, admin_id).await?;","typeGuard":null,"tryCatchPattern":"match db.move_channel(channel_id, new_parent_id, admin_id).await {\n    Ok(v) => Ok(v),\n    Err(err) if err.to_string().contains(\"WrongMoveTarget\") => {\n        Err(anyhow!(\"move target is in a different root channel\"))\n    }\n    Err(err) => Err(err),\n}","preventionTips":["Compare root_id() of dragged channel and drop target before offering the move","Only present drop targets from the current root's tree in the UI","Refresh the tree after every successful move so cached roots stay accurate"],"tags":["collab","channels","tree","validation"],"backgroundTag":null,"analyzedSha":"bc538def4545534201bbfcac4e95ac34ea6501b6","analyzedAt":"2026-08-16T07:30:46.435Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}