{"record":{"id":"06152f5355fc3872","repo":"siyuan-note/siyuan","slug":"document-block-s-cannot-be-moved-with-block-mov","errorCode":null,"errorMessage":"document block [%s] cannot be moved with block move; use document move instead","messagePattern":"document block \\[(.+?)\\] cannot be moved with block move; use document move instead","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/cli/cmd/block.go","lineNumber":440,"sourceCode":"\t\t}\n\t\tif err := model.PerformTxSync(transaction); err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif bt := treenode.GetBlockTree(id); bt != nil {\n\t\t\tmodel.AppendPushReloadProtyleEntry(bt.RootID)\n\t\t}\n\t\tfmt.Println(\"ok\")\n\t\treturn nil\n\t},\n}\n\nfunc validateBlockMove(id, parentID, previousID string) error {\n\tbt := treenode.GetBlockTree(id)\n\tif nil == bt {\n\t\treturn fmt.Errorf(\"block not found: %s\", id)\n\t}\n\tif \"d\" == bt.Type {\n\t\treturn fmt.Errorf(\"document block [%s] cannot be moved with block move; use document move instead\", id)\n\t}\n\n\tif \"\" != previousID {\n\t\tpreviousBt := treenode.GetBlockTree(previousID)\n\t\tif nil == previousBt {\n\t\t\treturn fmt.Errorf(\"previous block not found: %s\", previousID)\n\t\t}\n\t\tif \"d\" == previousBt.Type {\n\t\t\treturn fmt.Errorf(\"document block [%s] cannot be used as a previous sibling; use it as --parent instead\", previousID)\n\t\t}\n\t\treturn nil\n\t}\n\tif err := treenode.CheckListItemNesting(parentID, id); err != nil {\n\t\treturn err\n\t}\n\treturn treenode.CheckContainerParent(parentID)\n}\n","sourceCodeStart":422,"sourceCodeEnd":458,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/251596fc0de2f9528c00c224252fd073a99973f4/kernel/cli/cmd/block.go#L422-L458","documentation":"Thrown inside `validateBlockMove` when the block being moved has blocktree type `\"d\"` (document). SiYuan treats document blocks as notebook-level entities; relocating a document under another block via the block move transaction would create illegal nesting. The error routes the user to document-level move commands instead.","triggerScenarios":"Passing a document root block ID as `--id` to `block move`. Documents must be moved with the document/notebook move API, not the block move operation.","commonSituations":"Grabbing a document ID from the editor and using `block move`; assuming `block move` is generic for all block types; scripting doc reorganization with the wrong command.","solutions":["Use the document move API/command instead of `block move` for type-`d` blocks","Confirm the block type first: `siyuan-kernel block get --id <id>` and check the Type field","If you meant to move a child block inside the document, use that child's ID, not the document root ID"],"exampleFix":"// before\nsiyuan-kernel block move --id 20260605100657-v080a4j   # type 'd'\n// after\n# use the document move command for documents; use a non-document child block ID for block move","handlingStrategy":"validation","validationCode":"// Reject document blocks before calling move.\nbt := treenode.GetBlockTree(moverID)\nif bt == nil {\n    return fmt.Errorf(\"mover block %s not found\", moverID)\n}\nif bt.Type == \"d\" {\n    return fmt.Errorf(\"block %s is a document; use document move, not block move\", moverID)\n}","typeGuard":"func isDocumentBlock(id string) bool {\n    bt := treenode.GetBlockTree(id)\n    return bt != nil && bt.Type == \"d\"\n}","tryCatchPattern":null,"preventionTips":["Branch on block type in scripts: documents go to document-move, everything else to block-move","Use `block get` to inspect Type before choosing the command","Document IDs are often the same as file roots — flag them in tooling"],"tags":["cli","block","move","semantic","document","go"],"backgroundTag":null,"analyzedSha":"251596fc0de2f9528c00c224252fd073a99973f4","analyzedAt":"2026-08-12T21:18:37.123Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}