siyuan-note/siyuan · error

Conf.Language(314)

Error message

Conf.Language(314)

What it means

RollbackRepoSnapshotFile refuses to roll back a snapshot file that belongs to an encrypted notebook when that notebook is not currently mounted. If the notebook were not mounted, getRollbackBox would fall back to a plain (unencrypted) notebook and WriteTree would write the decrypted .sy content to disk as plaintext, violating the encrypted-notebook guarantee that decrypted data never crosses the encryption boundary. The error text comes from i18n key 314.

Source

Thrown at kernel/model/repository.go:298

	if err = os.WriteFile(from, data, 0644); nil != err {
		logging.LogErrorf("write file [%s] failed: %v", filepath.Join(tempRepoDiffDir, file.Path), err)
		return
	}
	// 解密后的临时文件在函数返回时清理,避免加密文档明文残留在磁盘
	defer os.Remove(from)

	if strings.HasSuffix(file.Path, ".sy") {
		boxID := strings.TrimPrefix(file.Path, "/")
		boxID = strings.Split(boxID, "/")[0]
		origBoxID := boxID // 保留原始 boxID 用于加密边界校验

		// 加密笔记本的快照回滚要求原笔记本已挂载:
		// WriteTree 根据 tree.Box 判断是否加密落盘。若原笔记本未挂载导致
		// getRollbackBox fallback 到普通 Rollback 笔记本,解密后的 .sy 将被 WriteTree
		// 以明文落盘,违反加密笔记本"数据不跨边界"的约束。
		if IsEncryptedBox(origBoxID) && nil == Conf.Box(origBoxID) {
			logging.LogErrorf("rollback encrypted repo snapshot requires notebook [%s] to be mounted", origBoxID)
			err = errors.New(Conf.Language(314))
			return
		}

		var box *Box
		var needResetTree bool
		box, needResetTree, err = getRollbackBox(boxID)
		if err != nil {
			logging.LogErrorf("get rollback box [%s] failed: %s", boxID, err)
			return
		}
		boxID = box.ID

		var destPath, parentHPath string
		rootID := util.GetTreeID(file.Path)
		workingDoc := treenode.GetBlockTree(rootID)
		if needResetTree {
			workingDoc = nil
		}

View on GitHub (pinned to 8641553a1f)

Solutions

  1. Open/mount the encrypted notebook in the SiYuan UI (or ensure it appears in the workspace notebook list) before rolling back the snapshot file
  2. Restart the kernel so all configured notebooks are mounted, then retry the rollback
  3. Verify the snapshot's boxID matches an existing notebook ID and that the notebook was not deleted
  4. If the notebook is intentionally gone, remove the stale snapshots instead of rolling back into it

Example fix

// before (fails: notebook closed)
RollbackRepoSnapshotFile(fileID)

// after: ensure the box is mounted first
box := Conf.Box(origBoxID)
if box == nil {
    // open/mount the notebook via the UI or OpenBox API, then retry
    RollbackRepoSnapshotFile(fileID)
}
Defensive patterns

Strategy: validation

Validate before calling

if !IsEncryptedBox(origBoxID) || Conf.Box(origBoxID) != nil {
    RollbackRepoSnapshotFile(fileID) // safe to proceed
}

Try / catch

if err := rollback(fileID); err != nil && strings.Contains(err.Error(), Conf.Language(314)) {
    // prompt user to mount the encrypted notebook, then retry
}

Prevention

When it happens

Trigger: Calling RollbackRepoSnapshotFile (via API repo/rollbackRepoFile) where the snapshot path resolves to origBoxID with IsEncryptedBox(origBoxID)==true while Conf.Box(origBoxID) returns nil — i.e. the encrypted notebook exists in the snapshot but is closed/not mounted in the workspace at rollback time.

Common situations: User closed the encrypted notebook (or it failed to mount at boot) and then tries to roll back one of its documents from the repo snapshot history; workspace restored from backup where notebooks.json no longer lists the encrypted notebook; encrypted notebook deleted but its snapshots still exist in the repo.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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