siyuan-note/siyuan · error

duplicated new item template id

Error message

duplicated new item template id [%s]

What it means

Template IDs within one NewItemTemplatesConfig must be unique; SetNewItemTemplates tracks seen IDs in templateIDs map and rejects duplicates with this error naming the repeated ID. Duplicate IDs would make default-template resolution and lookup ambiguous.

Solutions

  1. Assign a distinct valid node ID to every template in the config.
  2. Deduplicate by ID before calling SetNewItemTemplates (keep the last or first occurrence deliberately).
  3. When cloning a template for editing, regenerate its ID on save.

Example fix

// before
{id: "20240918120000-abcdef0123456789", name: "A"}, {id: "20240918120000-abcdef0123456789", name: "B"}
// after
{id: "20240918120000-abcdef0123456789", name: "A"}, {id: "20240918120001-0123456789abcdef", name: "B"}
Defensive patterns

Strategy: validation

Validate before calling

seen := map[string]bool{}
for _, t := range cfg.Templates {
	if seen[t.ID] { return fmt.Errorf("duplicate template id %s", t.ID) }
	seen[t.ID] = true
}

Prevention

When it happens

Trigger: Submitting a config where two or more templates share the same ID — commonly from copying an existing template entry without generating a new ID.

Common situations: Duplicating a template row in the settings UI; merging configs from two sources; round-tripping a config where a new template reused the old ID.

Understand the failure class

Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.

Related errors


AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19). Data as JSON: /api/errors/2abf76d2ae76cf71. Report an issue: GitHub.

Appendix: source

Thrown at kernel/av/new_item_template.go:70

			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 {
			return err
		}
		templates = append(templates, itemTemplate)

View on GitHub (pinned to 9f775e8a12)