{"record":{"id":"13f814b38047582c","repo":"siyuan-note/siyuan","slug":"decrypt-file-annotation-s-w","errorCode":null,"errorMessage":"decrypt file annotation [%s]: %w","messagePattern":"decrypt file annotation \\[(.+?)\\]: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/export.go","lineNumber":4379,"sourceCode":"\tassetBoxID := ExtractBoxIDFromAssetsPath(absPath)\n\tvar dek []byte\n\tif IsEncryptedBox(assetBoxID) {\n\t\tHoldBoxReadLock(assetBoxID)\n\t\tdefer ReleaseBoxReadLock(assetBoxID)\n\t\tdek, err = GetDEKIfUnlocked(assetBoxID)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tdefer clear(dek)\n\t}\n\tsyaData, readErr := os.ReadFile(sya)\n\tif readErr != nil {\n\t\treturn fmt.Errorf(\"read file annotation [%s]: %w\", sya, readErr)\n\t}\n\tif nil != dek {\n\t\tplain, decErr := DecryptAsset(assetBoxID, filepath.Base(sya), dek, syaData)\n\t\tif decErr != nil {\n\t\t\treturn fmt.Errorf(\"decrypt file annotation [%s]: %w\", sya, decErr)\n\t\t}\n\t\tsyaData = plain\n\t}\n\tsyaJSON := map[string]struct {\n\t\tPages []struct {\n\t\t\tIndex *int `json:\"index\"`\n\t\t} `json:\"pages\"`\n\t\tPage *int `json:\"page\"`\n\t}{}\n\tif err = gulu.JSON.UnmarshalJSON(syaData, &syaJSON); err != nil {\n\t\treturn fmt.Errorf(\"parse file annotation [%s]: %w\", sya, err)\n\t}\n\tannotationData, found := syaJSON[annotationID]\n\tpageIndex := annotationData.Page\n\tif 0 < len(annotationData.Pages) {\n\t\tpageIndex = annotationData.Pages[0].Index\n\t}\n\tif !found || nil == pageIndex || *pageIndex < 0 {","sourceCodeStart":4361,"sourceCodeEnd":4397,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/model/export.go#L4361-L4397","documentation":"For assets in encrypted notebooks, the .sya annotation data is ciphertext and is decrypted with the notebook's data-encryption key via DecryptAsset. If decryption or authentication fails (wrong key, corrupted or tampered ciphertext, version mismatch), the export aborts with this wrapped error instead of falling back to plaintext, per the encrypted-notebook compatibility policy.","triggerScenarios":"Exporting an annotation from a notebook whose MasterSalt/keys were regenerated or lost; .sya ciphertext corrupted by partial sync or manual editing; DecryptAsset rejects the payload because the basename or AAD does not match what was authenticated at write time.","commonSituations":"Workspace keys folder restored from an old backup while data came from a newer sync; user copied a .sya into a different encrypted notebook; truncated/corrupted file after an interrupted transfer; decrypting an asset that was written under an older envelope format version without its migration path.","solutions":["Restore the correct notebook encryption keys (do not regenerate MasterSalt); keep keys consistent between devices","Re-sync the notebook from a healthy replica to replace corrupted ciphertext","Verify the .sya resides in the same notebook it was encrypted for; move it back if misplaced","Ensure the kernel version supports the .sya envelope format version, or migrate via the supported recovery path"],"exampleFix":"// before: .sya copied into another encrypted notebook -> decrypt fails\nassets/report.pdf.sya  (in box-B, encrypted for box-A)\n// after: keep sidecar with its owning notebook\nassets/report.pdf.sya  (in box-A)","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  await exportAnnotation(docID);\n} catch (e) {\n  if (/decrypt file annotation/.test(e.message)) {\n    // do NOT retry with regenerated keys; restore keys from a working replica first\n    await restoreKeysFromReplica(boxID);\n    return exportAnnotation(docID);\n  }\n  throw e;\n}","preventionTips":["Never regenerate MasterSalt or delete the keys folder to 'fix' decryption errors","Keep keys and encrypted data in sync together across devices","Never copy .sya sidecars between different encrypted notebooks","Keep the kernel updated so supported envelope formats remain readable"],"tags":["export","encryption","decryption","file-annotation"],"backgroundTag":"checksum-mismatch","analyzedSha":"9f775e8a12daef8255556097396f9b2739078892","analyzedAt":"2026-09-19T03:17:15.984Z","contentChangedAt":"2026-09-19T03:17:15.984Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}