{"record":{"id":"5aa0f931c1d08bfd","repo":"siyuan-note/siyuan","slug":"new-option-name-already-exists","errorCode":null,"errorMessage":"new option name already exists","messagePattern":"new option name already exists","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/attribute_view_key_config.go","lineNumber":246,"sourceCode":"\t\tNewName *string `json:\"newName\"`\n\t\tColor   *string `json:\"color\"`\n\t\tDesc    *string `json:\"desc\"`\n\t}\n\tif err := decodeAttributeViewKeyConfig(value, &config); nil != err {\n\t\treturn err\n\t}\n\toption := key.GetOption(config.Name)\n\tif nil == option {\n\t\treturn errors.New(\"optionUpdate must name an existing option\")\n\t}\n\tname, color, desc := option.Name, option.Color, option.Desc\n\tif nil != config.NewName {\n\t\tname = strings.TrimSpace(*config.NewName)\n\t\tif \"\" == name {\n\t\t\treturn errors.New(\"new option name must not be empty\")\n\t\t}\n\t\tif name != option.Name && nil != key.GetOption(name) {\n\t\t\treturn errors.New(\"new option name already exists\")\n\t\t}\n\t}\n\tif nil != config.Color {\n\t\tcolor = *config.Color\n\t\tif attrView.FilterColorValue(color) != color {\n\t\t\treturn errors.New(\"invalid option color\")\n\t\t}\n\t}\n\tif nil != config.Desc {\n\t\tdesc = *config.Desc\n\t}\n\tif name == option.Name {\n\t\top.Data = []*av.SelectOption{{Name: name, Color: color, Desc: desc}}\n\t\treturn updateAttributeViewColumnOptions(op)\n\t}\n\top.Data = map[string]any{\"oldName\": option.Name, \"newName\": name, \"newColor\": color, \"newDesc\": desc}\n\treturn updateAttributeViewColumnOption(op)\n}","sourceCodeStart":228,"sourceCodeEnd":264,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/model/attribute_view_key_config.go#L228-L264","documentation":"updateAttributeViewKeyOptions updates an attribute-view select/multi-select option's name, color, and description. This error is thrown when the requested new option name differs from the current name but an option with that name already exists on the same key, since option names must be unique within a key.","triggerScenarios":"Calling UpdateAttributeViewKeyConfig with NewName set for a select-like key option where another option in the same key already has that name (case-exact match after TrimSpace).","commonSituations":"Renaming an option to a name that already exists (e.g. renaming 'todo' to 'Todo' is fine, but to 'done' when 'done' exists fails); concurrent edits where two clients rename options onto the same target name; scripted bulk reconfigurations that don't check existing option names.","solutions":["Pick a new option name that does not already exist in the key's option list","If the intent is to keep the name, omit config.NewName (or send the same name) so the duplicate check is skipped","List the key's current options first and skip or merge duplicates programmatically"],"exampleFix":"// before\nconfig := &conf.AttributeViewKeyConfig{KeyID: keyID, OptionID: optID, NewName: strPtr(\"done\")}\nUpdateAttributeViewKeyConfig(avID, viewID, config) // fails: 'done' exists\n// after\nif key.GetOption(\"done\") == nil {\n    config := &conf.AttributeViewKeyConfig{KeyID: keyID, OptionID: optID, NewName: strPtr(\"done\")}\n    UpdateAttributeViewKeyConfig(avID, viewID, config)\n}","handlingStrategy":"validation","validationCode":"// JS caller: check the name is free before updating\nconst key = av.keys.find(k => k.id === keyID);\nif (key.options.some(o => o.name === newName && o.id !== optionID)) {\n  throw new Error(`Option name \"${newName}\" already exists`);\n}","typeGuard":null,"tryCatchPattern":"try {\n  await api.updateAttributeViewKeyConfig({avID, keyID, optionID, newName});\n} catch (e) {\n  if (e.message.includes('new option name already exists')) {\n    // pick another name or merge options\n  }\n}","preventionTips":["List existing option names before renaming","Trim and compare names case-sensitively as the kernel does","For renames to an existing name, merge values instead of renaming"],"tags":["attribute-view","duplicate-name","validation"],"backgroundTag":"duplicate-option-name","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"}