{"record":{"id":"9283f59ac8b96f82","repo":"siyuan-note/siyuan","slug":"invalid-file-annotation-reference-s","errorCode":null,"errorMessage":"invalid file annotation reference [%s]","messagePattern":"invalid file annotation reference \\[(.+?)\\]","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/export.go","lineNumber":4341,"sourceCode":"\n\t\tif n.ID == id {\n\t\t\tret = true\n\t\t\treturn ast.WalkStop\n\t\t}\n\t\treturn ast.WalkContinue\n\t})\n\treturn\n}\n\ntype refAsFootnotes struct {\n\trefNum        string\n\trefAnchorText string\n}\n\nfunc processFileAnnotationRef(refID string, n *ast.Node, fileAnnotationRefMode int, boxID string) error {\n\tassetLink, annotationID := util.SplitFileAnnotationRef(refID)\n\tif \"\" == annotationID {\n\t\treturn fmt.Errorf(\"invalid file annotation reference [%s]\", refID)\n\t}\n\tp, query, _ := splitAssetReference(assetLink)\n\tassetLink = p\n\tif \"\" != query {\n\t\tassetLink += \"?\" + query\n\t}\n\tlookupLink := p\n\tif decodedPath, decodeErr := url.PathUnescape(p); nil == decodeErr {\n\t\tlookupLink = decodedPath\n\t}\n\tif \"\" != query {\n\t\tlookupLink += \"?\" + query\n\t}\n\tabsPath, err := GetAssetAbsPathInBox(lookupLink, boxID)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"resolve file annotation asset [%s]: %w\", assetLink, err)\n\t}\n\tsya := absPath + \".sya\"","sourceCodeStart":4323,"sourceCodeEnd":4359,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/model/export.go#L4323-L4359","documentation":"processFileAnnotationRef parses a file-annotation reference of the form produced by util.SplitFileAnnotationRef. If the refID does not contain a valid annotation ID portion (empty after splitting), the reference is malformed and the export fails with 'invalid file annotation reference [%s]'.","triggerScenarios":"Export (PDF/annotation processing) encounters a node whose file-annotation-ref attribute holds a string that splits into an empty annotationID — e.g. truncated, hand-edited, or plugin-written refID without the '@'-separated annotation id part.","commonSituations":"Document content edited by an older/plugin version writing malformed annotation refs; PDF asset replaced so annotation links got corrupted; manual editing of .sy content breaking the ref format.","solutions":["Fix or remove the malformed file annotation reference in the source document (re-insert the annotation from the PDF asset)","Check the refID format: it must be '<assetPath>@<annotationID>'; regenerate the link via the UI's file annotation feature","If encountered in bulk, validate all file-annotation-ref attributes in the notebook and repair or strip invalid ones"],"exampleFix":"// before\n<span data-type=\"file-annotation-ref\" data-id=\"assets/paper.pdf@\">text</span> // empty annotation id\n// after\n<span data-type=\"file-annotation-ref\" data-id=\"assets/paper.pdf@page=2&loc=...\">text</span>","handlingStrategy":"type-guard","validationCode":"function isValidFileAnnotationRef(refId) {\n  const idx = refId.indexOf('@');\n  return idx > 0 && refId.slice(idx + 1).length > 0;\n}","typeGuard":"const hasAnnotationID = ref => typeof ref === 'string' && ref.split('@').length === 2 && ref.split('@')[1] !== '';","tryCatchPattern":"try { await exportPDF(id); }\ncatch (e) {\n  const m = String(e).match(/invalid file annotation reference \\[(.+)\\]/);\n  if (m) { repairOrRemoveAnnotationRef(m[1]); await retryExport(); }\n}","preventionTips":["Never hand-edit data-id attributes of file-annotation-ref spans","Re-create broken annotations from the PDF asset via the UI instead of patching raw text","Validate notebook content for malformed annotation refs before batch exports"],"tags":["export","file-annotation","pdf"],"backgroundTag":"invalid-identifier-format","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"}