{"record":{"id":"4edfd2b95edeabe2","repo":"siyuan-note/siyuan","slug":"invalid-new-item-template-id-s","errorCode":null,"errorMessage":"invalid new item template id [%s]","messagePattern":"invalid new item template id \\[(.+?)\\]","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/av/new_item_template.go","lineNumber":67,"sourceCode":"\t\t}\n\t\titemTemplate = cloneNewItemTemplate(itemTemplate)\n\t\tif nil == itemTemplate {\n\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 {","sourceCodeStart":49,"sourceCodeEnd":85,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/av/new_item_template.go#L49-L85","documentation":"SetNewItemTemplates requires each template's ID to match ast.IsNodeIDPattern (a valid SiYuan node ID like 20240101120000-abcdefgh). IDs failing this pattern make the config invalid and abort the update, with the offending ID embedded via %s.","triggerScenarios":"Passing a template with an empty, custom, or malformed ID (wrong length, missing dash separator, non-hex suffix).","commonSituations":"Generating IDs client-side with random strings instead of the SiYuan ID format; copying truncated IDs; legacy or hand-crafted config files.","solutions":["Assign a valid node-format ID (yyyymmddhhmmss-16hexchars) to every template.","Use the kernel's treenode/id helper to generate IDs instead of hand-rolling them.","Check IDs with ast.IsNodeIDPattern before calling SetNewItemTemplates."],"exampleFix":"// before\n{id: \"tpl-1\"}\n// after\n{id: \"20240918120000-abcdef0123456789\"}","handlingStrategy":"validation","validationCode":"for _, t := range cfg.Templates {\n\tif !ast.IsNodeIDPattern(t.ID) { return fmt.Errorf(\"bad template id %s\", t.ID) }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Generate IDs with the kernel's node-ID helper, never random strings","Validate IDs with ast.IsNodeIDPattern before submitting","Never truncate or reformat IDs when copying configs"],"tags":["attribute-view","identifier","validation","go"],"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"}