siyuan-note/siyuan · error

document not found or empty

Error message

document not found or empty

What it means

Thrown by `block stat` when `filesys.StatTree(id)` returns nil. `StatTree` returns nil if the tree cannot be loaded — `LoadTrees` yields no tree (block not in blocktree, or the .sy file is unreadable/missing). This is a data-state error, not an argument error: `--id` was present but resolves to nothing.

Source

Thrown at kernel/cli/cmd/block.go:168

		if mode == "" {
			mode = "md"
		}
		fmt.Print(model.GetBlockKramdown(id, mode))
		return nil
	},
}

var blockStatCmd = &cobra.Command{
	Use:   "stat --id <id>",
	Short: "Get block content statistics",
	RunE: func(cmd *cobra.Command, args []string) error {
		id, _ := cmd.Flags().GetString("id")
		if id == "" {
			return fmt.Errorf("--id is required")
		}
		stat := filesys.StatTree(id)
		if stat == nil {
			return fmt.Errorf("document not found or empty")
		}
		switch outputFormat {
		case "json":
			data, _ := json.MarshalIndent(stat, "", "  ")
			fmt.Println(string(data))
		default:
			fmt.Printf("Characters: %d\n", stat.RuneCount)
			fmt.Printf("Words:      %d\n", stat.WordCount)
			fmt.Printf("Blocks:     %d\n", stat.BlockCount)
			fmt.Printf("Links:      %d\n", stat.LinkCount)
			fmt.Printf("Images:     %d\n", stat.ImageCount)
			fmt.Printf("Refs:       %d\n", stat.RefCount)
		}
		return nil
	},
}

// ─── Write ─────────────────────────────────────────────────────────────────────

View on GitHub (pinned to 251596fc0d)

Solutions

  1. Verify the ID exists: `siyuan-kernel block get --id <id>` or query `siyuan-kernel sql "SELECT * FROM blocks WHERE id='<id>'"`
  2. Ensure the notebook containing the block is mounted/opened in the active workspace
  3. For encrypted notebooks, unlock them first so `LoadTrees` can read the `.sy` files
  4. If the file was moved/deleted, reindex or use the correct ID

Example fix

// before
siyuan-kernel block stat --id 00000000000000-nonexist
// after
siyuan-kernel block stat --id 20260605100657-v080a4j  # confirmed via `sql` first
Defensive patterns

Strategy: validation

Validate before calling

// Pre-check existence before calling `block stat` to avoid the nil-tree error.
// In a Go caller of the model layer:
bt := treenode.GetBlockTree(docID)
if bt == nil {
    return fmt.Errorf("document %s not found in blocktree", docID)
}
stat := filesys.StatTree(docID)
if stat == nil {
    return fmt.Errorf("document %s could not be loaded", docID)
}

Type guard

// isLoadableDoc returns true when a tree can be resolved for the given root id.
func isLoadableDoc(id string) bool {
    if strings.TrimSpace(id) == "" {
        return false
    }
    return treenode.GetBlockTree(id) != nil
}

Prevention

When it happens

Trigger: Passing an `--id` that is not a registered block in `blocktrees`, belongs to a notebook that is not opened/mounted, points to an encrypted notebook whose key is unloaded, or whose `.sy` file was deleted/corrupted on disk.

Common situations: Workspace not fully mounted at CLI time; referencing a block ID from another workspace; encrypted notebook locked; the document was deleted but an old ID was cached; running the CLI before the kernel finished indexing.

Related errors


AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12). Data as JSON: /api/errors/d52471af38115b48. Report an issue: GitHub.