{"record":{"id":"8dc657636dd5a0dd","repo":"siyuan-note/siyuan","slug":"new-item-template-field-s-option-s-not-found","errorCode":null,"errorMessage":"new item template field [%s] option [%s] not found","messagePattern":"new item template field \\[(.+?)\\] option \\[(.+?)\\] not found","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/av/new_item_template.go","lineNumber":339,"sourceCode":"\t\t}\n\t\tswitch fieldValue.Mode {\n\t\tcase NewItemFieldValueCurrentTime:\n\t\t\tif KeyTypeDate != key.Type {\n\t\t\t\treturn fmt.Errorf(\"new item template field [%s] current time mode requires date type\", keyID)\n\t\t\t}\n\t\t\tfieldValue.Value = nil\n\t\tcase NewItemFieldValueStatic:\n\t\t\tif nil == fieldValue.Value {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tfieldValue.Value, err = normalizeNewItemTemplateValue(fieldValue.Value, key)\n\t\t\tif nil != err {\n\t\t\t\treturn fmt.Errorf(\"new item template field [%s] value is invalid: %w\", keyID, err)\n\t\t\t}\n\t\t\tif KeyTypeSelect == key.Type || KeyTypeMSelect == key.Type {\n\t\t\t\tfor _, selection := range fieldValue.Value.MSelect {\n\t\t\t\t\tif nil != selection && nil == key.GetOption(selection.Content) {\n\t\t\t\t\t\treturn fmt.Errorf(\"new item template field [%s] option [%s] not found\", keyID, selection.Content)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\tdefault:\n\t\t\treturn fmt.Errorf(\"invalid new item template field value mode [%s]\", fieldValue.Mode)\n\t\t}\n\t\tfieldValues[keyID] = fieldValue\n\t}\n\tif 0 == len(fieldValues) {\n\t\titemTemplate.FieldValues = nil\n\t} else {\n\t\titemTemplate.FieldValues = fieldValues\n\t}\n\treturn nil\n}\n\nfunc normalizeNewItemTemplateValue(value *Value, key *Key) (*Value, error) {\n\tvalue = value.Clone()","sourceCodeStart":321,"sourceCodeEnd":357,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/251596fc0de2f9528c00c224252fd073a99973f4/kernel/av/new_item_template.go#L321-L357","documentation":"For Select/MSelect Static-mode values, each selection.Content must resolve to an existing option on the key via key.GetOption(content). Selecting an option that was deleted or renamed is rejected, because the picker would render a dangling reference.","triggerScenarios":"An option is deleted or renamed while the template editor is open; the client caches a stale option list; an import references options that do not exist on this key; concurrent option edits between two clients.","commonSituations":"Sync applying remote option changes locally; user reorganizing option list after the template was last saved; copy of a template between AVs whose option sets differ.","solutions":["Refresh the option list client-side before saving and remap or drop stale selections.","When renaming an option server-side, use RenameNewItemTemplateSelectOption (new_item_template.go:135) to keep templates in sync.","When deleting an option server-side, use RemoveNewItemTemplateSelectOption (new_item_template.go:130) in the same transaction."],"exampleFix":"// before — references a removed option\nValue.MSelect = []*av.ValueSelect{{Content: \"old-opt\"}}\n// after\nValue.MSelect = []*av.ValueSelect{{Content: \"renamed-opt\"}}","handlingStrategy":"validation","validationCode":"if key.Type == av.KeyTypeSelect || key.Type == av.KeyTypeMSelect {\n    for _, sel := range value.MSelect {\n        if sel != nil && key.GetOption(sel.Content) == nil {\n            return fmt.Errorf(\"option [%s] not found\", sel.Content)\n        }\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Refresh the option list client-side before saving.","On option rename/delete server-side, call Rename/RemoveNewItemTemplateSelectOption in the same transaction.","Map stale option names to their renamed equivalents before submit."],"tags":["av","new-item-template","select","option","validation","stale-reference"],"backgroundTag":null,"analyzedSha":"251596fc0de2f9528c00c224252fd073a99973f4","analyzedAt":"2026-08-12T21:18:37.123Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}