{"record":{"id":"656565541d543ddb","repo":"siyuan-note/siyuan","slug":"missing-or-invalid-annotation-s-in-s","errorCode":null,"errorMessage":"missing or invalid annotation [%s] in [%s]","messagePattern":"missing or invalid annotation \\[(.+?)\\] in \\[(.+?)\\]","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/export.go","lineNumber":4398,"sourceCode":"\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 {\n\t\treturn fmt.Errorf(\"missing or invalid annotation [%s] in [%s]\", annotationID, sya)\n\t}\n\tpageStr := strconv.Itoa(*pageIndex + 1)\n\n\trefText := n.TextMarkTextContent\n\text := filepath.Ext(p)\n\tfile := strings.TrimPrefix(strings.TrimSuffix(p, ext), \"assets/\")\n\t// 仅剥离完整的节点 ID 后缀，无后缀文件及短文件名保持原样。\n\tif len(file) > 23 && file[len(file)-23] == '-' && ast.IsNodeIDPattern(file[len(file)-22:]) {\n\t\tfile = file[:len(file)-23]\n\t}\n\tfile += ext\n\tfileAnnotationRefLink := &ast.Node{Type: ast.NodeLink}\n\tfileAnnotationRefLink.AppendChild(&ast.Node{Type: ast.NodeOpenBracket})\n\tif 0 == fileAnnotationRefMode {\n\t\tfileAnnotationRefLink.AppendChild(&ast.Node{Type: ast.NodeLinkText, Tokens: []byte(file + \" - p\" + pageStr + \" - \" + refText)})\n\t} else {\n\t\tfileAnnotationRefLink.AppendChild(&ast.Node{Type: ast.NodeLinkText, Tokens: []byte(refText)})\n\t}","sourceCodeStart":4380,"sourceCodeEnd":4416,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/model/export.go#L4380-L4416","documentation":"After parsing the .sya JSON, the kernel looks up the requested annotationID; the entry must exist and carry a usable page number (either \"page\" or pages[0].index, not null and >= 0). Missing ID or invalid page data aborts the export with this error.","triggerScenarios":"Exporting an annotation whose ID is not present in the parsed .sya map; the entry has neither page nor pages[0].index (both null); the resolved page index is negative.","commonSituations":"Stale annotation reference in the document after the annotation was deleted from the PDF; hand-edited .sya missing fields; annotation IDs changed when the PDF was re-annotated with a different tool.","solutions":["Verify the annotationID exists as a key in the .sya JSON and has a valid page/index integer >= 0","Recreate the annotation in the PDF so the sidecar regenerates a valid entry","Restore the .sya from version history if fields were removed by editing","Update the document's annotation reference to point to an existing annotation ID"],"exampleFix":"// before: missing page in sidecar entry\n{\"ann-1\": {}}\n// after\n{\"ann-1\": {\"page\": 0}}","handlingStrategy":"validation","validationCode":"function annotationIsExportable(syaJSON, annotationID) {\n  const a = syaJSON[annotationID];\n  if (!a) return false;\n  const idx = a.pages && a.pages.length ? a.pages[0].index : a.page;\n  return typeof idx === \"number\" && idx >= 0;\n}","typeGuard":"function hasValidPage(a) {\n  const idx = a?.pages?.[0]?.index ?? a?.page;\n  return typeof idx === \"number\" && Number.isInteger(idx) && idx >= 0;\n}","tryCatchPattern":"try {\n  await exportAnnotation(docID);\n} catch (e) {\n  if (/missing or invalid annotation/.test(e.message)) {\n    // recreate the annotation or export without it\n    console.warn(\"Skipping invalid annotation\", e.message);\n  }\n}","preventionTips":["Recreate annotations instead of editing their IDs in the document text","Re-check references after re-annotating a PDF with a different tool","Clean up document references when deleting annotations"],"tags":["export","file-annotation","validation","pdf"],"backgroundTag":"record-not-found","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"}