siyuan-note/siyuan · error
new option name already exists
Error message
new option name already exists
What it means
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.
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
Example fix
// before
config := &conf.AttributeViewKeyConfig{KeyID: keyID, OptionID: optID, NewName: strPtr("done")}
UpdateAttributeViewKeyConfig(avID, viewID, config) // fails: 'done' exists
// after
if key.GetOption("done") == nil {
config := &conf.AttributeViewKeyConfig{KeyID: keyID, OptionID: optID, NewName: strPtr("done")}
UpdateAttributeViewKeyConfig(avID, viewID, config)
} Defensive patterns
Strategy: validation
Validate before calling
// JS caller: check the name is free before updating
const key = av.keys.find(k => k.id === keyID);
if (key.options.some(o => o.name === newName && o.id !== optionID)) {
throw new Error(`Option name "${newName}" already exists`);
} Try / catch
try {
await api.updateAttributeViewKeyConfig({avID, keyID, optionID, newName});
} catch (e) {
if (e.message.includes('new option name already exists')) {
// pick another name or merge options
}
} Prevention
- 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
When it happens
Trigger: 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).
Common situations: 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.
Related errors
- at least one visible view is required
- attribute view custom color index
- attribute view custom color must not be null
- attribute view custom colors count exceeds the
- attribute view custom colors must not be empty
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/5aa0f931c1d08bfd.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/model/attribute_view_key_config.go:246
NewName *string `json:"newName"`
Color *string `json:"color"`
Desc *string `json:"desc"`
}
if err := decodeAttributeViewKeyConfig(value, &config); nil != err {
return err
}
option := key.GetOption(config.Name)
if nil == option {
return errors.New("optionUpdate must name an existing option")
}
name, color, desc := option.Name, option.Color, option.Desc
if nil != config.NewName {
name = strings.TrimSpace(*config.NewName)
if "" == name {
return errors.New("new option name must not be empty")
}
if name != option.Name && nil != key.GetOption(name) {
return errors.New("new option name already exists")
}
}
if nil != config.Color {
color = *config.Color
if attrView.FilterColorValue(color) != color {
return errors.New("invalid option color")
}
}
if nil != config.Desc {
desc = *config.Desc
}
if name == option.Name {
op.Data = []*av.SelectOption{{Name: name, Color: color, Desc: desc}}
return updateAttributeViewColumnOptions(op)
}
op.Data = map[string]any{"oldName": option.Name, "newName": name, "newColor": color, "newDesc": desc}
return updateAttributeViewColumnOption(op)
}View on GitHub (pinned to 9f775e8a12)