siyuan-note/siyuan · error
invalid new item template id
Error message
invalid new item template id [%s]
What it means
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.
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.
Example fix
// before
{id: "tpl-1"}
// after
{id: "20240918120000-abcdef0123456789"} Defensive patterns
Strategy: validation
Validate before calling
for _, t := range cfg.Templates {
if !ast.IsNodeIDPattern(t.ID) { return fmt.Errorf("bad template id %s", t.ID) }
} Prevention
- 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
When it happens
Trigger: Passing a template with an empty, custom, or malformed ID (wrong length, missing dash separator, non-hex suffix).
Common situations: Generating IDs client-side with random strings instead of the SiYuan ID format; copying truncated IDs; legacy or hand-crafted config files.
Understand the failure class
Background: "invalid id" errors: invalid identifier format — why libraries reject IDs before lookup, and how to fix them — this error's family across 37 libraries.
Related errors
- duplicated new item template id
- ErrInvalidAttributeViewID
- ErrInvalidBoxID
- ErrInvalidID
- filter nesting depth exceeds the maximum allowed
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/4edfd2b95edeabe2.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/av/new_item_template.go:67
}
itemTemplate = cloneNewItemTemplate(itemTemplate)
if nil == itemTemplate {
return errors.New("clone new item template failed")
}
itemTemplate.Name = strings.TrimSpace(itemTemplate.Name)
itemTemplate.Icon = strings.TrimSpace(itemTemplate.Icon)
if filteredIcon, valid := util.FilterIconValue(itemTemplate.Icon); valid {
itemTemplate.Icon = filteredIcon
} else {
// 非法图标值置空,防止存储可执行标记
// https://github.com/siyuan-note/siyuan/security/advisories/GHSA-vx5w-qrvp-mmcq
itemTemplate.Icon = ""
}
if "" == itemTemplate.Name {
return errors.New("new item template name is empty")
}
if !ast.IsNodeIDPattern(itemTemplate.ID) {
return fmt.Errorf("invalid new item template id [%s]", itemTemplate.ID)
}
if templateIDs[itemTemplate.ID] {
return fmt.Errorf("duplicated new item template id [%s]", itemTemplate.ID)
}
templateIDs[itemTemplate.ID] = true
if NewItemTargetDetached != itemTemplate.TargetType && NewItemTargetDocument != itemTemplate.TargetType {
return fmt.Errorf("invalid new item template target type [%s]", itemTemplate.TargetType)
}
if NewItemTargetDocument != itemTemplate.TargetType {
itemTemplate.Icon = ""
itemTemplate.HideInFileTree = false
}
itemTemplate.ContentTemplatePath = strings.TrimSpace(itemTemplate.ContentTemplatePath)
if nil != itemTemplate.SaveLocation {
itemTemplate.SaveLocation.BoxID = strings.TrimSpace(itemTemplate.SaveLocation.BoxID)
itemTemplate.SaveLocation.PathTemplate = strings.TrimSpace(itemTemplate.SaveLocation.PathTemplate)
}
if err := av.normalizeNewItemTemplateFieldValues(itemTemplate); nil != err {View on GitHub (pinned to 9f775e8a12)