siyuan-note/siyuan · error
duplicate option name
Error message
duplicate option name
What it means
The 'options' setting replaces the whole option list, and option names must be unique within a select/mselect field because they are the cell value identity. A submitted list containing the same name twice is rejected.
Solutions
- Deduplicate the option array by Name before sending
- Send one entry per option; update metadata of an existing option via "optionUpdate" instead of adding a second entry
- Normalize names (trim) before the uniqueness check client-side
Example fix
// before
[{"name":"Todo"},{"name":"Todo","color":"2"}]
// after
[{"name":"Todo","color":"2"}] Defensive patterns
Strategy: validation
Validate before calling
const names = options.map(o => o.name);
if (new Set(names).size !== names.length) throw new Error("duplicate option names in payload"); Prevention
- Deduplicate by name before sending the options list
- Keep a single source of truth for the option list instead of merging arrays ad hoc
When it happens
Trigger: Calling UpdateAttributeViewKeyConfig with setting "options" where two entries share the same Name string (exact match, after no normalization other than the non-empty check).
Common situations: Merging option lists from two sources without deduplication; duplicating an entry when editing the payload by hand; case-variant duplicates like "todo" and "Todo" are distinct here but visually confusing, while exact duplicates fail.
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
- each option requires a nonempty name
- invalid option color
- new option name must not be empty
- option settings require a select or mSelect field
- optionRemove must name an existing option
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/7ce8f28f0a5a2244.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/model/attribute_view_key_config.go:208
return decoder.Decode(dest)
}
func updateAttributeViewKeyOptions(attrView *av.AttributeView, key *av.Key, op *Operation, setting string, value any) error {
if "options" == setting {
var options []*av.SelectOption
if err := decodeAttributeViewKeyConfig(value, &options); nil != err {
return err
}
if 0 == len(options) {
return errors.New("options must not be empty; use optionRemove to delete existing options")
}
names := map[string]bool{}
for _, option := range options {
if nil == option || "" == strings.TrimSpace(option.Name) {
return errors.New("each option requires a nonempty name")
}
if names[option.Name] {
return errors.New("duplicate option name")
}
if attrView.FilterColorValue(option.Color) != option.Color {
return errors.New("invalid option color")
}
names[option.Name] = true
}
op.Data = options
return updateAttributeViewColumnOptions(op)
}
if "optionRemove" == setting {
name, ok := value.(string)
if !ok || nil == key.GetOption(name) {
return errors.New("optionRemove must name an existing option")
}
op.Data = name
return removeAttributeViewColumnOption(op)
}
var config struct {View on GitHub (pinned to 9f775e8a12)