siyuan-note/siyuan · error

ErrBoxNotFound

ErrBoxNotFound

Error message

notebook not found

What it means

ErrBoxNotFound is the sentinel error returned when a notebook (box) ID does not exist in the workspace — e.g. lookups of the notebook directory fail. API handlers compare with errors.Is to translate it into client-facing data such as an 'unavailable notebook' payload for attribute-view item creation.

Solutions

  1. List notebooks (GET /api/notebook/lsNotebooks) and confirm the boxID exists; correct the ID in the caller
  2. Re-add or reopen the notebook if it was removed from the workspace
  3. Refresh any cached notebook IDs in your integration before calling CreateAttributeViewItemDocs
  4. Handle errors.Is(err, model.ErrBoxNotFound) in your client to surface 'unavailable notebook' instead of a raw error

Example fix

// before
value, err := model.CreateAttributeViewItemDocs(avID, blockID, mode, ids)
if err != nil { return err }

// after
if err != nil {
    if errors.Is(err, model.ErrBoxNotFound) {
        return apicontract.CreateAttributeViewItemDocs.FailureWithData(1, "",
            apicontract.NewAVCreateItemDocsResultError(apicontract.AVUnavailableNotebook{UnavailableNotebook: true}))
    }
    return err
}
Defensive patterns

Strategy: try-catch

Validate before calling

// TypeScript: verify notebook exists before the call
const boxes = await fetchPost('/api/notebook/lsNotebooks', {});
if (!boxes.data.notebooks.includes(boxID)) throw new Error('notebook missing: ' + boxID);

Type guard

function isBoxNotFound(err: unknown): err is Error {
  return err instanceof Error && err.message === 'notebook not found';
}

Try / catch

// Go
if errors.Is(err, model.ErrBoxNotFound) {
    return apicontract.CreateAttributeViewItemDocs.FailureWithData(1, "",
        apicontract.NewAVCreateItemDocsResultError(apicontract.AVUnavailableNotebook{UnavailableNotebook: true}))
}

Prevention

When it happens

Trigger: model.CreateAttributeViewItemDocs (or other notebook-consuming operations) is called with a boxID that has no matching notebook in the workspace, or a save-config resolution derives a notebook ID that does not exist; handlers at kernel/api/av.go:361 and kernel/api/av_contract_render.go:66 map it to AVUnavailableNotebook.

Common situations: Client caches a stale notebook ID after the notebook was deleted or its .si folder removed; typo'd or malformed notebook ID in an API call; notebook added on another profile/workspace; attribute view references a doc whose notebook was removed.

Understand the failure class

Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.

Related errors


AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19). Data as JSON: /api/errors/2563bd4b149693dd. Report an issue: GitHub.

Appendix: source

Thrown at kernel/model/tree.go:210

		if data, err = DecryptFile(boxID, relPath, dek, data); err != nil {
			logging.LogErrorf("decrypt tree [path=%s] failed: %s", localPath, err)
			return
		}
	}

	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
	}

View on GitHub (pinned to 9f775e8a12)