siyuan-note/siyuan · error

encrypted repository data is missing valid notebook context

Error message

encrypted repository data is missing valid notebook context

What it means

Inside OpenRepoSnapshotFile after reading file bytes: the data tests positive as ciphertext (util.IsCiphertext or the encryptedAssetMagic prefix) but the extracted payloadBoxID is empty or does not name a registered encrypted notebook. This is a deliberate fail-closed check: encrypted bytes without a decryptable notebook context must never be handed to a plaintext parser. Distinct from 866 (which lives in decryptRepoDataIfNeeded and keys off path validity) — here the check is on the snapshot payload path prefix.

Source

Thrown at kernel/model/repository.go:425

	if err != nil {
		return
	}

	data, err := repo.OpenFile(file)
	if err != nil {
		return
	}

	updated = file.Updated
	repoPath := strings.TrimPrefix(file.Path, "/")
	repoPathParts := strings.SplitN(repoPath, "/", 2)
	payloadBoxID := ""
	if len(repoPathParts) == 2 && ast.IsNodeIDPattern(repoPathParts[0]) {
		payloadBoxID = repoPathParts[0]
	}
	if (util.IsCiphertext(data) || bytes.HasPrefix(data, encryptedAssetMagic)) &&
		(payloadBoxID == "" || !IsEncryptedBox(payloadBoxID)) {
		err = errors.New("encrypted repository data is missing valid notebook context")
		return
	}

	if strings.HasSuffix(file.Path, ".sy") {
		// 加密笔记本的 .sy 在仓库里是密文,按路径提取 boxID 解密
		data, err = decryptRepoDataIfNeeded(data, file.Path)
		if err != nil {
			return
		}
		luteEngine := NewLute()
		var snapshotTree *parse.Tree
		displayInText, snapshotTree, err = parseTreeInSnapshot(data, luteEngine)
		if err != nil {
			logging.LogErrorf("parse tree from snapshot file [%s] failed", fileID)
			return
		}
		title = snapshotTree.Root.IALAttr("title")

View on GitHub (pinned to 251596fc0d)

Solutions

  1. Check the kernel log for the file.Path that triggered it and confirm the leading path segment is a valid 20-char boxID that still exists.
  2. If the notebook was deleted, the ciphertext is orphaned — remove/ignore that snapshot object; do not attempt to force-decrypt.
  3. Restore the missing notebook's .siyuan/conf.json (with Encrypted=true) so IsEncryptedBox(payloadBoxID) returns true and the decrypt path engages.
  4. Recover from an earlier intact snapshot index if the repo store is inconsistent.
Defensive patterns

Strategy: validation

Validate before calling

// Validate the snapshot file path carries a real encrypted boxID before opening
parts := strings.SplitN(strings.TrimPrefix(file.Path, "/"), "/", 2)
if (util.IsCiphertext(data) || bytes.HasPrefix(data, encryptedAssetMagic)) {
    if len(parts) < 2 || !ast.IsNodeIDPattern(parts[0]) || !model.IsEncryptedBox(parts[0]) {
        return errors.New("encrypted snapshot object has no decryptable notebook context")
    }
}

Prevention

When it happens

Trigger: Opening a snapshot file whose stored path is malformed (no leading /<boxID>/) yet whose bytes are ciphertext; or an encrypted box that was unregistered/its conf.json removed while ciphertext objects still reference it.

Common situations: Repository store inconsistency after manual editing, a botched notebook deletion that left ciphertext objects, or cross-workspace copying of a repo store whose notebook IDs do not exist in the target workspace.

Related errors


AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12). Data as JSON: /api/errors/3758df93da12965d. Report an issue: GitHub.