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

  1. Pick a new option name that does not already exist in the key's option list
  2. If the intent is to keep the name, omit config.NewName (or send the same name) so the duplicate check is skipped
  3. 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

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


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)