{"record":{"id":"2abf76d2ae76cf71","repo":"siyuan-note/siyuan","slug":"duplicated-new-item-template-id-s","errorCode":null,"errorMessage":"duplicated new item template id [%s]","messagePattern":"duplicated new item template id \\[(.+?)\\]","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/av/new_item_template.go","lineNumber":70,"sourceCode":"\t\t\treturn errors.New(\"clone new item template failed\")\n\t\t}\n\t\titemTemplate.Name = strings.TrimSpace(itemTemplate.Name)\n\t\titemTemplate.Icon = strings.TrimSpace(itemTemplate.Icon)\n\t\tif filteredIcon, valid := util.FilterIconValue(itemTemplate.Icon); valid {\n\t\t\titemTemplate.Icon = filteredIcon\n\t\t} else {\n\t\t\t// 非法图标值置空，防止存储可执行标记\n\t\t\t// https://github.com/siyuan-note/siyuan/security/advisories/GHSA-vx5w-qrvp-mmcq\n\t\t\titemTemplate.Icon = \"\"\n\t\t}\n\t\tif \"\" == itemTemplate.Name {\n\t\t\treturn errors.New(\"new item template name is empty\")\n\t\t}\n\t\tif !ast.IsNodeIDPattern(itemTemplate.ID) {\n\t\t\treturn fmt.Errorf(\"invalid new item template id [%s]\", itemTemplate.ID)\n\t\t}\n\t\tif templateIDs[itemTemplate.ID] {\n\t\t\treturn fmt.Errorf(\"duplicated new item template id [%s]\", itemTemplate.ID)\n\t\t}\n\t\ttemplateIDs[itemTemplate.ID] = true\n\t\tif NewItemTargetDetached != itemTemplate.TargetType && NewItemTargetDocument != itemTemplate.TargetType {\n\t\t\treturn fmt.Errorf(\"invalid new item template target type [%s]\", itemTemplate.TargetType)\n\t\t}\n\t\tif NewItemTargetDocument != itemTemplate.TargetType {\n\t\t\titemTemplate.Icon = \"\"\n\t\t\titemTemplate.HideInFileTree = false\n\t\t}\n\t\titemTemplate.ContentTemplatePath = strings.TrimSpace(itemTemplate.ContentTemplatePath)\n\t\tif nil != itemTemplate.SaveLocation {\n\t\t\titemTemplate.SaveLocation.BoxID = strings.TrimSpace(itemTemplate.SaveLocation.BoxID)\n\t\t\titemTemplate.SaveLocation.PathTemplate = strings.TrimSpace(itemTemplate.SaveLocation.PathTemplate)\n\t\t}\n\t\tif err := av.normalizeNewItemTemplateFieldValues(itemTemplate); nil != err {\n\t\t\treturn err\n\t\t}\n\t\ttemplates = append(templates, itemTemplate)","sourceCodeStart":52,"sourceCodeEnd":88,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/251596fc0de2f9528c00c224252fd073a99973f4/kernel/av/new_item_template.go#L52-L88","documentation":"Two entries in config.Templates carry the same ID. The validator tracks seen IDs in a map (new_item_template.go:69) and rejects the second occurrence, because persisted template references (DefaultTemplateID, per-row bindings) require uniqueness within the AV.","triggerScenarios":"Frontend clones a template in the editor without minting a new ID; an import payload contains duplicated IDs; copy-paste of a template JSON followed by save.","commonSituations":"Client-side clone button that copies all fields including ID; sync conflict resolution that duplicated a template; manually authored config in tests.","solutions":["Regenerate the ID for any duplicated template before submitting.","Dedupe template IDs on the client before the save call.","When cloning in UI code, always assign a freshly generated node ID."],"exampleFix":"// before\nTemplates: []*av.NewItemTemplate{{ID: \"20240812...abc\"}, {ID: \"20240812...abc\"}}\n// after\nTemplates: []*av.NewItemTemplate{{ID: \"20240812...abc\"}, {ID: \"20240812...def\"}}","handlingStrategy":"validation","validationCode":"seen := map[string]bool{}\nfor _, t := range config.Templates {\n    if t == nil {\n        continue\n    }\n    if seen[t.ID] {\n        return fmt.Errorf(\"duplicated new item template id [%s]\", t.ID)\n    }\n    seen[t.ID] = true\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["When cloning a template in the UI, always mint a fresh node ID.","Dedupe on the client before submitting the batch.","Add a unit test that asserts ID uniqueness in imported configs."],"tags":["av","new-item-template","duplicate","validation","uniqueness"],"backgroundTag":null,"analyzedSha":"251596fc0de2f9528c00c224252fd073a99973f4","analyzedAt":"2026-08-12T21:18:37.123Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}