siyuan-note/siyuan · error
block [ ] is not a document
Error message
block [%s] is not a document
What it means
GetDocBlocksOrders collects the block ordering structure of a document tree, but it first verifies that the given ID actually belongs to the tree's root document block. If the tree loaded for `id` has a root whose ID differs from the requested ID, the kernel rejects the call because only a document (root) ID is valid here, not a child block or arbitrary ID.
Solutions
- Pass the document's root ID (tree.Root.ID), not a child block ID — e.g. query `SELECT root_id FROM blocks WHERE id = ?` first
- Verify the document still exists and matches the ID (check for sync/renames that changed the root ID)
- Trim/validate the ID string for typos or truncation before calling
- Handle the error by falling back to resolving the parent document of the block instead of failing
Example fix
// before
orders, err := model.GetDocBlocksOrders(blockID) // blockID may be a child
// after
var rootID string
row := db.QueryRow("SELECT root_id FROM blocks WHERE id = ?", blockID)
row.Scan(&rootID)
orders, err := model.GetDocBlocksOrders(rootID) Defensive patterns
Strategy: validation
Validate before calling
function isDocID(id string, db *sql.DB) bool {
var rootID string
return db.QueryRow("SELECT root_id FROM blocks WHERE id = ?", id).Scan(&rootID) == nil && rootID == id
} Try / catch
orders, err := model.GetDocBlocksOrders(id)
if err != nil && strings.Contains(err.Error(), "is not a document") {
// resolve parent document and retry
} Prevention
- Always pass tree.Root.ID / blocks.root_id, never a child block ID
- Validate IDs exist and are roots before calling document-level APIs
- Refresh cached doc IDs after sync or reindex
When it happens
Trigger: Calling GetDocBlocksOrders (or the API surface that wraps it) with: (1) a child-block ID instead of the document ID; (2) a stale/deleted document ID whose tree resolution falls back to a different root; (3) a mistyped or truncated block ID.
Common situations: Plugins or scripts iterate the SQL blocks table and pass non-root block IDs; code caches document IDs from a previous session that no longer match after re-index or sync; user-supplied IDs from links contain an anchor block ID rather than the doc ID.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- block [ ] is not a document that can declare a child…
- source document [ ] is not a sibling of target document [ ]
- source document [ ] not found
- target document [ ] not found
- boot appearance asset forbidden
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/d70b8b7912c59283.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/model/blockinfo.go:596
for _, id := range ids {
ret[id] = nodesIndexes[id]
}
return
}
func GetDocBlocksOrders(id string) (ret []string, err error) {
ret = []string{}
tree, err := LoadTreeByBlockID(id)
if err != nil {
return
}
if nil == tree || nil == tree.Root {
err = ErrTreeNotFound
return
}
if tree.Root.ID != id {
err = fmt.Errorf("block [%s] is not a document", id)
return
}
ret = getDocBlocksOrdersInTree(tree)
return
}
func getDocBlocksOrdersInTree(tree *parse.Tree) (ret []string) {
ret = []string{}
ast.Walk(tree.Root, func(n *ast.Node, entering bool) ast.WalkStatus {
if !entering || n == tree.Root || !n.IsBlock() || ast.NodeKramdownBlockIAL == n.Type || "" == n.ID {
return ast.WalkContinue
}
ret = append(ret, n.ID)
return ast.WalkContinue
})
returnView on GitHub (pinned to 9f775e8a12)