siyuan-note/siyuan · error

encrypted attribute view history is missing notebook context

Error message

encrypted attribute view history is missing notebook context [%s]

What it means

When rolling back a document that contains attribute views (databases) from an encrypted notebook, the kernel needs the AV definition file from history. For encrypted boxes the AV may live under the boxID subdirectory of the history entry; if that file does not exist, the kernel cannot restore the database consistently with the document and fails with this error naming the attribute view ID.

Source

Thrown at kernel/model/history.go:384

	if tree == nil {
		return errors.New("parse document history failed")
	}
	if encrypted && tree.Root.ID+".sy" != filepath.Base(historyPath) {
		return errors.New("encrypted document history root ID does not match its filename")
	}
	if nil != tree {
		historyDir := filepath.Join(util.HistoryDir, parts[0])

		avNodes := tree.Root.ChildrenByType(ast.NodeAttributeView)
		for _, avNode := range avNodes {
			srcAvPath := filepath.Join(historyDir, "storage", "av", avNode.AttributeViewID+".json")
			// 加密笔记本的 AV 定义在笔记本级目录
			destAvPath := filepath.Join(util.DataDir, "storage", "av", avNode.AttributeViewID+".json")
			if IsEncryptedBox(boxID) {
				// 历史目录里 AV 也可能在 boxID 子目录下
				boxSrcAvPath := filepath.Join(historyDir, boxID, "storage", "av", avNode.AttributeViewID+".json")
				if !gulu.File.IsExist(boxSrcAvPath) {
					return fmt.Errorf("encrypted attribute view history is missing notebook context [%s]", avNode.AttributeViewID)
				}
				srcAvPath = boxSrcAvPath
				destAvPath = filepath.Join(util.DataDir, boxID, "storage", "av", avNode.AttributeViewID+".json")
			}
			if gulu.File.IsExist(destAvPath) {
				if copyErr := filelock.CopyNewtimes(srcAvPath, destAvPath); nil != copyErr {
					logging.LogErrorf("copy av [%s] failed: %s", srcAvPath, copyErr)
				}
				cache.RemoveAVData(avNode.AttributeViewID)
			}

			avIDs = append(avIDs, avNode.AttributeViewID)
		}
	}
	avIDs = gulu.Str.RemoveDuplicatedElem(avIDs)

	tree.Box = boxID
	tree.Path = filepath.ToSlash(strings.TrimPrefix(destPath, util.DataDir+string(os.PathSeparator)+boxID))

View on GitHub (pinned to 8641553a1f)

Solutions

  1. Ensure the history entry includes storage/av/<avID>.json under the boxID directory before rolling back
  2. Choose a more recent history snapshot that contains the AV definition
  3. Restore the missing AV history file from backup, then retry the rollback
  4. Remove the database block from the document (or accept losing AV rollback) if the AV history is unrecoverable

Example fix

// before: snapshot without AV history
ls data/history/20260910/encBox/storage/av/  # missing 20250101120000-av1.json
// after: pick a snapshot that includes it
ls data/history/20260911/encBox/storage/av/  # 20250101120000-av1.json present, use that entry
Defensive patterns

Strategy: validation

Validate before calling

const avIds = docAvIds // attribute view IDs referenced by the document
for (const avId of avIds) {
  const p = `data/history/${dateSeg}/${boxID}/storage/av/${avId}.json`
  if (!(await fileExists(p))) throw new Error(`history missing AV file ${avId}`)
}

Try / catch

try {
  await fetchPost("/api/history/rollbackDocHistory", {historyPath})
} catch (e) {
  if (String(e.msg || e).includes("missing notebook context")) {
    // select a snapshot that includes storage/av definitions
  }
}

Prevention

When it happens

Trigger: rollbackDocHistory on an encrypted notebook's document containing NodeAttributeView nodes, where data/history/<date>/<boxID>/storage/av/<avID>.json is absent — history was captured before the AV was created, or the history entry lacks the storage/av portion.

Common situations: Rolling back to a very old snapshot that predates the database block; history pruning that removed storage/av files but kept document snapshots; manually cleaning the history directory and deleting AV files.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


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