siyuan-note/siyuan · error
encrypted repository data has no matching notebook [%s]
Error message
encrypted repository data has no matching notebook [%s]
What it means
decryptRepoDataIfNeeded: the path's boxID segment is a valid node ID, but IsEncryptedBox(boxID) is false AND the bytes are ciphertext. This means the notebook is not registered as encrypted, so there is no DEK to decrypt with — fail-closed. The boxID is included in the message. Contrast with 866 (invalid boxID format) and 868 (valid encrypted box but locked).
Source
Thrown at kernel/model/repository.go:748
// 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]
// 按路径类型分流
if strings.HasPrefix(boxRelPath, "assets/") {
diskName := filepath.Base(boxRelPath)
plain, decErr := DecryptAsset(boxID, diskName, dek, data)
if decErr != nil {
return nil, decErr
}View on GitHub (pinned to 251596fc0d)
Solutions
- Verify whether the named boxID should be encrypted; if so, restore its .siyuan/conf.json with Encrypted=true and the same key material.
- If the notebook genuinely is not encrypted, the ciphertext object is orphaned/corrupt — remove it or rebuild the repo index.
- Restore from a consistent snapshot set where path and encryption flag agree.
Defensive patterns
Strategy: validation
Validate before calling
// Reject ciphertext whose boxID is not a registered encrypted notebook
rel := strings.TrimPrefix(filePath, "/")
parts := strings.SplitN(rel, "/", 2)
if len(parts) == 2 && ast.IsNodeIDPattern(parts[0]) && !model.IsEncryptedBox(parts[0]) {
if util.IsCiphertext(data) || bytes.HasPrefix(data, encryptedAssetMagic) {
return fmt.Errorf("encrypted repository data has no matching notebook [%s]", parts[0])
}
} Prevention
- Keep the Encrypted flag in each notebook's conf.json consistent with its stored objects.
- When deleting/un-encrypting a notebook, clean up its ciphertext repo objects too.
- Investigate any boxID reported in this message — it signals store/notebook mismatch.
When it happens
Trigger: A snapshot object carries ciphertext for a notebook whose conf.json no longer marks it Encrypted (e.g. it was downgraded/removed), or ciphertext leaked into a normal notebook's path during a botched copy/restore.
Common situations: Notebook un-encrypted or deleted but ciphertext objects remain in the repo store; restoring a backup of conf.json that lost the Encrypted flag; cross-workspace repo copy.
Related errors
- encrypted repository data is missing valid notebook context
- encrypted repository data is missing notebook context
- 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/3730f4a624990daf.
Report an issue: GitHub.