{"record":{"id":"91204753b1e79f69","repo":"siyuan-note/siyuan","slug":"duplicate-encrypted-document-id-s","errorCode":null,"errorMessage":"duplicate encrypted document ID [%s]","messagePattern":"duplicate encrypted document ID \\[(.+?)\\]","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"kernel/model/encrypted_index.go","lineNumber":82,"sourceCode":"\t\t\treturn fmt.Errorf(\"encrypted document is a symbolic link [%s]\", entry.Name())\n\t\t}\n\t\tdata, err := filelock.ReadFile(filePath)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tplain, err := DecryptFile(boxID, entry.Name(), dek, data)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\ttree, err := loadTreeByData0(plain)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif tree == nil || tree.Root == nil || tree.Root.ID+\".sy\" != entry.Name() {\n\t\t\treturn fmt.Errorf(\"encrypted document root ID does not match filename [%s]\", entry.Name())\n\t\t}\n\t\tif _, exists := ids[tree.Root.ID]; exists {\n\t\t\treturn fmt.Errorf(\"duplicate encrypted document ID [%s]\", tree.Root.ID)\n\t\t}\n\t\tids[tree.Root.ID] = struct{}{}\n\t\treturn nil\n\t})\n}\n","sourceCodeStart":64,"sourceCodeEnd":88,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/8641553a1f07374001902d3ce773285db1292b2d/kernel/model/encrypted_index.go#L64-L88","documentation":"The encrypted index rebuild collects every document root ID in a set; if two .sy files decrypt to documents with the same root ID, the second occurrence aborts the rebuild with this error. The SQLite index keys blocks by ID, so duplicates would corrupt block resolution, making this a hard integrity failure.","triggerScenarios":"Two files in the encrypted box's documents directory contain (decrypted) documents with identical root IDs — e.g. a document was duplicated by file copy (copy-of-<id>.sy) while the copy operation duplicated content instead of assigning a fresh ID, or a sync conflict left both the original and a byte-identical/mutated copy under different names.","commonSituations":"cp/duplicate file operations performed directly on the data directory instead of via the app (which assigns new IDs); restore of overlapping sync snapshots; manual merging of two workspaces containing the same document.","solutions":["Identify both files whose decrypted root IDs collide and delete or move out the stale/unwanted duplicate.","If both copies are wanted, re-import the duplicate through the app so it receives a fresh root ID, then rebuild indexes.","Restore the box data directory from a clean sync snapshot and retry the rebuild."],"exampleFix":"// before\ndata/boxes/<box>/20240101120000-abc.sy\ndata/boxes/<box>/20240101120000-abc (copy).sy  // same root ID\n// after\ndelete \"20240101120000-abc (copy).sy\" or re-import it in-app with a new ID","handlingStrategy":"validation","validationCode":"seen := map[string]string{} // rootID -> filename\nfor _, f := range syFiles {\n    id := rootIDFromTree(f)\n    if prev, dup := seen[id]; dup {\n        return fmt.Errorf(\"%s and %s share root ID %s\", prev, f, id)\n    }\n    seen[id] = f\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Duplicate blocks/documents only through the app UI or transactions API","Avoid copying .sy files directly in the data directory","De-duplicate after restoring overlapping sync snapshots"],"tags":["encryption","index","duplicate-id","integrity"],"backgroundTag":"internal-invariant-violation","analyzedSha":"8641553a1f07374001902d3ce773285db1292b2d","analyzedAt":"2026-09-11T16:08:28.414Z","contentChangedAt":"2026-09-11T16:08:28.414Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}