{"record":{"id":"bdb26d280f30a262","repo":"siyuan-note/siyuan","slug":"read-file-annotation-s-w","errorCode":null,"errorMessage":"read file annotation [%s]: %w","messagePattern":"read file annotation \\[(.+?)\\]: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/export.go","lineNumber":4374,"sourceCode":"\tif err != nil {\n\t\treturn fmt.Errorf(\"resolve file annotation asset [%s]: %w\", assetLink, err)\n\t}\n\tsya := absPath + \".sya\"\n\t// 以实际资源所属笔记本认证标注密文，读取失败时保留源文件并中止导出。\n\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]","sourceCodeStart":4356,"sourceCodeEnd":4392,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/model/export.go#L4356-L4392","documentation":"After resolving the annotation asset, the kernel reads the sibling .sya annotation sidecar file with os.ReadFile. Any OS-level read failure (missing file, permission denied, path too long) is wrapped as this error and aborts the annotation export, keeping the source file untouched.","triggerScenarios":"Exporting a file annotation whose <asset>.sya sidecar does not exist next to the PDF, or is unreadable due to filesystem permissions, sync placeholder files, or disk errors.","commonSituations":"PDF annotated elsewhere but the .sya file never synced; the sidecar was cleaned up by a sync tool; read-only mount or permission issue in the workspace data folder; case-sensitivity mismatch on Linux mounts.","solutions":["Check that a .sya file with the exact same name as the PDF exists next to it in assets/","Fix filesystem permissions on the assets directory so the kernel process can read it","Re-sync the notebook so the missing .sya sidecar is restored","Recreate the annotation if the sidecar is permanently lost"],"exampleFix":"// before\nassets/report.pdf          (no sidecar)\n// after\nassets/report.pdf\nassets/report.pdf.sya      (restored via sync or re-created annotation)","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  await exportAnnotation(docID);\n} catch (e) {\n  if (/read file annotation/.test(e.message)) {\n    // re-sync the notebook, then retry once\n    await syncNotebook(boxID);\n    return exportAnnotation(docID);\n  }\n  throw e;\n}","preventionTips":["Ensure .sya sidecars are included in backups and sync (not excluded patterns)","Fix workspace directory permissions so the kernel can read assets/","Watch for case-sensitivity mismatches when moving data between OS filesystems"],"tags":["export","file-annotation","file-read","sidecar"],"backgroundTag":"file-read-failed","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"}