siyuan-note/siyuan · error

notebook not found

Error message

notebook not found

What it means

Sentinel error model.ErrBoxNotFound (kernel/model/tree.go:202). It means the notebook (box) ID is not among the configured notebooks - Conf.GetBox(boxID) returned nil (kernel/model/mount.go:57). It is returned by many file/document operations (file.go, transaction.go, box_doc.go, attribute_view_new_item.go) whenever a boxID parameter cannot be resolved.

Solutions

  1. List current notebooks via /api/notebook/lsNotebooks and use one of the returned ids
  2. If the notebook should exist, check you are in the right workspace and reopen or recreate the notebook
  3. Match with errors.Is(err, model.ErrBoxNotFound) and refresh cached IDs instead of retrying blindly
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-check the notebook exists in this workspace:
// GET /api/notebook/lsNotebooks -> notebooks[].id
// In Go: if nil == Conf.GetBox(boxID) { /* refresh ids, abort */ }

Type guard

func isBoxNotFound(err error) bool {
	return errors.Is(err, model.ErrBoxNotFound)
}

Try / catch

if err := someFileOp(boxID, ...); err != nil {
	if errors.Is(err, model.ErrBoxNotFound) {
		// notebook id is stale: re-list notebooks and refresh cached ids
	} else {
		// propagate
	}
}

Prevention

When it happens

Trigger: API calls carrying a boxID that no longer exists in conf: the notebook was deleted or recreated with a new ID, the ID comes from a different workspace, or it is simply mistyped. Examples: /api/filetree/* ops with a stale box id, transactions targeting an unresolvable box (transaction.go:2417).

Common situations: Plugins caching box IDs across workspace switches or after notebook recreation; scripts exported from another machine; nightly jobs running against the wrong workspace.

Related errors


AI-assisted analysis of siyuan-note/siyuan@afa823b6b4 (2026-08-18). Data as JSON: /api/errors/d446a4e189ad465d. Report an issue: GitHub.

Appendix: source

Thrown at kernel/model/tree.go:202

		}
		// 从绝对路径推导 box 内相对路径作为 AAD
		relPath := filepath.ToSlash(strings.TrimPrefix(localPath, filepath.Join(util.DataDir, boxID)+string(os.PathSeparator)))
		if data, err = DecryptFile(boxID, relPath, dek, data); err != nil {
			logging.LogErrorf("decrypt tree [path=%s] failed: %s", localPath, 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
	}

View on GitHub (pinned to afa823b6b4)