{"record":{"id":"3758df93da12965d","repo":"siyuan-note/siyuan","slug":"encrypted-repository-data-is-missing-valid-noteboo","errorCode":null,"errorMessage":"encrypted repository data is missing valid notebook context","messagePattern":"encrypted repository data is missing valid notebook context","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/repository.go","lineNumber":425,"sourceCode":"\tif err != nil {\n\t\treturn\n\t}\n\n\tdata, err := repo.OpenFile(file)\n\tif err != nil {\n\t\treturn\n\t}\n\n\tupdated = file.Updated\n\trepoPath := strings.TrimPrefix(file.Path, \"/\")\n\trepoPathParts := strings.SplitN(repoPath, \"/\", 2)\n\tpayloadBoxID := \"\"\n\tif len(repoPathParts) == 2 && ast.IsNodeIDPattern(repoPathParts[0]) {\n\t\tpayloadBoxID = repoPathParts[0]\n\t}\n\tif (util.IsCiphertext(data) || bytes.HasPrefix(data, encryptedAssetMagic)) &&\n\t\t(payloadBoxID == \"\" || !IsEncryptedBox(payloadBoxID)) {\n\t\terr = errors.New(\"encrypted repository data is missing valid notebook context\")\n\t\treturn\n\t}\n\n\tif strings.HasSuffix(file.Path, \".sy\") {\n\t\t// 加密笔记本的 .sy 在仓库里是密文，按路径提取 boxID 解密\n\t\tdata, err = decryptRepoDataIfNeeded(data, file.Path)\n\t\tif err != nil {\n\t\t\treturn\n\t\t}\n\t\tluteEngine := NewLute()\n\t\tvar snapshotTree *parse.Tree\n\t\tdisplayInText, snapshotTree, err = parseTreeInSnapshot(data, luteEngine)\n\t\tif err != nil {\n\t\t\tlogging.LogErrorf(\"parse tree from snapshot file [%s] failed\", fileID)\n\t\t\treturn\n\t\t}\n\t\ttitle = snapshotTree.Root.IALAttr(\"title\")\n","sourceCodeStart":407,"sourceCodeEnd":443,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/251596fc0de2f9528c00c224252fd073a99973f4/kernel/model/repository.go#L407-L443","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["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.","If the notebook was deleted, the ciphertext is orphaned — remove/ignore that snapshot object; do not attempt to force-decrypt.","Restore the missing notebook's .siyuan/conf.json (with Encrypted=true) so IsEncryptedBox(payloadBoxID) returns true and the decrypt path engages.","Recover from an earlier intact snapshot index if the repo store is inconsistent."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Validate the snapshot file path carries a real encrypted boxID before opening\nparts := strings.SplitN(strings.TrimPrefix(file.Path, \"/\"), \"/\", 2)\nif (util.IsCiphertext(data) || bytes.HasPrefix(data, encryptedAssetMagic)) {\n    if len(parts) < 2 || !ast.IsNodeIDPattern(parts[0]) || !model.IsEncryptedBox(parts[0]) {\n        return errors.New(\"encrypted snapshot object has no decryptable notebook context\")\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never strip path prefixes from repo objects; the leading boxID segment drives decryption.","Keep notebook conf.json consistent with the encryption flag of objects that reference it.","Run repo consistency checks after manual workspace edits."],"tags":["repo","snapshot","encryption","data-integrity","fail-closed"],"backgroundTag":null,"analyzedSha":"251596fc0de2f9528c00c224252fd073a99973f4","analyzedAt":"2026-08-12T21:18:37.123Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}