siyuan-note/siyuan · error
load block tree [%s] failed: %w
Error message
load block tree [%s] failed: %w
What it means
Returned by buildBlockUpdateOperations when loadTree(input.ID) returns a non-nil error. The cache lookup (resolveTree + treeCache) missed, so the loader was invoked; the loader failed for some underlying reason which is wrapped with %w. The ID itself passed IsNodeIDPattern - this is a storage/IO failure.
Source
Thrown at kernel/model/block_update.go:113
data, dataTree, parseErr := parseBlockUpdateData(input.Data, input.DataType, luteEngine)
if parseErr != nil {
return nil, nil, parseErr
}
var oldTree *parse.Tree
var cacheKey blockUpdateTreeKey
hasCacheKey := false
if blockTree := resolveTree(input.ID); nil != blockTree {
cacheKey = blockUpdateTreeKey{boxID: blockTree.BoxID, rootID: blockTree.RootID}
hasCacheKey = true
oldTree = treeCache[cacheKey]
}
if nil == oldTree {
var loadErr error
oldTree, loadErr = loadTree(input.ID)
if loadErr != nil {
return nil, nil, fmt.Errorf("load block tree [%s] failed: %w", input.ID, loadErr)
}
if nil == oldTree || nil == oldTree.Root {
return nil, nil, fmt.Errorf("load block tree [%s] failed: tree is empty", input.ID)
}
treeCache[blockUpdateTreeKey{boxID: oldTree.Box, rootID: oldTree.ID}] = oldTree
if hasCacheKey {
treeCache[cacheKey] = oldTree
}
}
oldNode := treenode.GetNodeInTree(oldTree, input.ID)
if nil == oldNode {
return nil, nil, fmt.Errorf("block [%s] not found", input.ID)
}
if _, ok := rootIDSet[oldTree.ID]; !ok {
rootIDSet[oldTree.ID] = struct{}{}
rootIDs = append(rootIDs, oldTree.ID)
}View on GitHub (pinned to 251596fc0d)
Solutions
- Inspect the wrapped error (errors.Unwrap or %w chain) for the OS-level cause.
- Verify the .sy file exists at the expected path under data/<box>/<path>.sy.
- Restore from history/snapshot if the file is corrupted.
- Rebuild the index after restoring the file.
Defensive patterns
Strategy: try-catch
Validate before calling
if _, err := os.Stat(expectedSyPath(id)); err != nil {
return fmt.Errorf("sy file missing for %s", id)
} Try / catch
ops, roots, err := buildBlockUpdateOperations(inputs, resolver, loader)
if err != nil {
if cause := errors.Unwrap(err); cause != nil {
log.Warnf("load failed: %v", cause)
}
// fall back: rebuild index, then retry once
} Prevention
- Ensure the .sy file for the root exists on disk before updates.
- Keep snapshots/history enabled so corrupted .sy files can be restored.
- Inspect wrapped errors with errors.Unwrap to find the OS-level cause.
When it happens
Trigger: Missing .sy file for the block's root; corrupted .sy file that fails to unmarshal; filelock contention; disk/permission error; network share hiccup.
Common situations: Out-of-band deletion of the .sy file; partial sync that left an incomplete file; mobile storage permission revoked mid-operation.
Related errors
- Uninstall failed: %s
- load block tree [%s] failed: tree is empty
- failed to make directory: %w
- failed to write file: %w
- export source [%s] is not a regular file
AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12).
Data as JSON: /api/errors/3bcf78442e3f79f8.
Report an issue: GitHub.