siyuan-note/siyuan · error

ErrTreeNotFound

ErrTreeNotFound

Error message

tree not found

What it means

ErrTreeNotFound is the sentinel error meaning the document tree for a given ID could not be loaded. Doc-info and path-lookup functions (getDocInfo, getBlockInfo, getHPathByID, getFullHPathByID, export prep) return it when no tree matches the ID. API handlers deliberately swallow it in some endpoints because 'not found' should degrade quietly rather than surface as a message.

Source

Thrown at kernel/model/tree.go:213

		}
	}

	if err = treenode.CheckSpecJSON(data); nil != err {
		return
	}
	ret, err = dataparser.ParseJSONWithoutFix(data, luteEngine.ParseOptions)
	if err != nil {
		logging.LogErrorf("parse json to tree [%s] failed: %s", localPath, err)
		return
	}
	return
}

var (
	ErrBoxNotFound   = errors.New("notebook not found")
	ErrBoxClosed     = errors.New("notebook closed")
	ErrBlockNotFound = errors.New("block not found")
	ErrTreeNotFound  = errors.New("tree not found")
	ErrIndexing      = errors.New("indexing")
	ErrBoxUnindexed  = errors.New("notebook unindexed")
	ErrInvalidID     = errors.New("invalid id")
)

func LoadTreeByBlockIDWithReindex(id string) (ret *parse.Tree, err error) {
	return LoadTreeByBlockIDWithReindexInBox(id, "")
}

// LoadTreeByBlockIDWithReindexInBox 与 LoadTreeByBlockIDWithReindex 一致,但按 boxID 路由 blocktree 查询。
func LoadTreeByBlockIDWithReindexInBox(id, boxID string) (ret *parse.Tree, err error) {
	if "" == id {
		logging.LogWarnf("block id is empty")
		return nil, ErrTreeNotFound
	}

	bt := treenode.GetBlockTreeInBox(id, boxID)
	if nil == bt && "" == boxID {

View on GitHub (pinned to 8641553a1f)

Solutions

  1. Confirm the document still exists (/api/filetree/getHPathByID) and update or remove stale references to the deleted doc
  2. Rebuild the notebook index if the .sy file exists but the in-memory/blocktree index lost it
  3. Handle errors.Is(err, model.ErrTreeNotFound) as an expected 'missing' case in API callers (as block.go:710 does) instead of reporting an error message

Example fix

// before
ret.Msg = err.Error()
// after
if err != nil && !errors.Is(err, model.ErrTreeNotFound) {
    ret.Msg = err.Error()
}
Defensive patterns

Strategy: try-catch

Validate before calling

hp, err := getHPathByID(id)
if err != nil || hp == "" { return fmt.Errorf("doc %s not found", id) }

Try / catch

if errors.Is(err, model.ErrTreeNotFound) {
    // treat as expected missing-doc case; degrade quietly
    return nil
}

Prevention

When it happens

Trigger: getDocInfo/getBlockInfo called with an ID absent from the index; getHPathByID/getPathByID/getFullHPathByID with a deleted doc's ID; prepareExportAssets encountering a missing tree during export.

Common situations: Client or plugin requesting a document deleted on another device before sync removed it locally; corrupted blocktree index missing the tree; links/bookmarks pointing at removed documents.

Understand the failure class

Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.

Related errors


AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11). Data as JSON: /api/errors/4562081f91cefdb5. Report an issue: GitHub.