siyuan-note/siyuan · error
encrypted repository data is missing notebook context
Error message
encrypted repository data is missing notebook context
What it means
decryptRepoDataIfNeeded: the data is ciphertext (IsCiphertext or encryptedAssetMagic) but the file path splits into fewer than 2 parts or its first segment is not a valid node ID (20-char boxID). With no valid boxID the code cannot route decryption, and fail-closed semantics forbid treating ciphertext as plaintext. Distinct from 862 (payload-context check in the caller) and 867 (boxID valid but not a registered encrypted box).
Source
Thrown at kernel/model/repository.go:741
}
title = tree.Root.IALAttr("title")
rootID = tree.Root.ID
}
return
}
// decryptRepoDataIfNeeded 判断仓库数据是否属于加密笔记本,如果是则按路径类型分流解密。
// file.Path 格式:/<boxID>/...
// .sy → DecryptFile,assets/* → DecryptAsset,storage/av/*.json → av.DecryptAVData。
// 密文缺少有效路径上下文、笔记本未解锁或认证失败时返回错误,不允许调用方按明文继续处理。
func decryptRepoDataIfNeeded(data []byte, filePath string) ([]byte, error) {
relPath := strings.TrimPrefix(filePath, "/")
parts := strings.SplitN(relPath, "/", 2)
encryptedPayload := util.IsCiphertext(data) || bytes.HasPrefix(data, encryptedAssetMagic)
if len(parts) < 2 || !ast.IsNodeIDPattern(parts[0]) {
if encryptedPayload {
return nil, errors.New("encrypted repository data is missing notebook context")
}
return data, nil
}
boxID := parts[0]
if !IsEncryptedBox(boxID) {
if encryptedPayload {
return nil, fmt.Errorf("encrypted repository data has no matching notebook [%s]", boxID)
}
return data, nil
}
// 持读锁,防止 LockBox 在解密期间清 DEK/缓存
HoldBoxReadLock(boxID)
defer ReleaseBoxReadLock(boxID)
dek, err := GetDEKIfUnlocked(boxID)
if err != nil {
return nil, errors.New(Conf.Language(314))
}
boxRelPath := parts[1]View on GitHub (pinned to 251596fc0d)
Solutions
- Check the logged filePath and confirm it starts with /<20-char-boxID>/.
- If the repo index is corrupt, reset the data repo and rebuild from a known-good snapshot set.
- Do not strip or rewrite path prefixes to bypass the check — it exists to prevent decrypting ciphertext without a key.
Defensive patterns
Strategy: validation
Validate before calling
// Reject ciphertext whose path cannot yield a valid boxID
rel := strings.TrimPrefix(filePath, "/")
parts := strings.SplitN(rel, "/", 2)
encrypted := util.IsCiphertext(data) || bytes.HasPrefix(data, encryptedAssetMagic)
if encrypted && (len(parts) < 2 || !ast.IsNodeIDPattern(parts[0])) {
return errors.New("encrypted repository data is missing notebook context")
} Prevention
- Preserve the /<boxID>/ prefix on every repo object path.
- Run integrity checks after any manual repo-store manipulation.
- Never rewrite this guard to fall back to plaintext for ciphertext.
When it happens
Trigger: A snapshot object whose path is malformed (no /<boxID>/ prefix, or boxID segment not matching ast.IsNodeIDPattern) while its stored bytes are ciphertext; reached during rollback/open/export of such a file.
Common situations: Corrupted repo index pointing at a misnamed object; manually relocated/renamed snapshot files; cross-version repo store with a path-format change.
Related errors
- encrypted repository data is missing valid notebook context
- encrypted repository data has no matching notebook [%s]
- encrypted .sy [%s]: base id [%s] != root id [%s]
- encrypted attribute view snapshot is missing notebook contex
- encrypted attribute view snapshot has no matching notebook [
AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12).
Data as JSON: /api/errors/137d2d4384429836.
Report an issue: GitHub.