{"record":{"id":"4f96aae2671c3d03","repo":"siyuan-note/siyuan","slug":"invalid-option-color","errorCode":null,"errorMessage":"invalid option color","messagePattern":"invalid option color","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/attribute_view_key_config.go","lineNumber":211,"sourceCode":"func updateAttributeViewKeyOptions(attrView *av.AttributeView, key *av.Key, op *Operation, setting string, value any) error {\n\tif \"options\" == setting {\n\t\tvar options []*av.SelectOption\n\t\tif err := decodeAttributeViewKeyConfig(value, &options); nil != err {\n\t\t\treturn err\n\t\t}\n\t\tif 0 == len(options) {\n\t\t\treturn errors.New(\"options must not be empty; use optionRemove to delete existing options\")\n\t\t}\n\t\tnames := map[string]bool{}\n\t\tfor _, option := range options {\n\t\t\tif nil == option || \"\" == strings.TrimSpace(option.Name) {\n\t\t\t\treturn errors.New(\"each option requires a nonempty name\")\n\t\t\t}\n\t\t\tif names[option.Name] {\n\t\t\t\treturn errors.New(\"duplicate option name\")\n\t\t\t}\n\t\t\tif attrView.FilterColorValue(option.Color) != option.Color {\n\t\t\t\treturn errors.New(\"invalid option color\")\n\t\t\t}\n\t\t\tnames[option.Name] = true\n\t\t}\n\t\top.Data = options\n\t\treturn updateAttributeViewColumnOptions(op)\n\t}\n\tif \"optionRemove\" == setting {\n\t\tname, ok := value.(string)\n\t\tif !ok || nil == key.GetOption(name) {\n\t\t\treturn errors.New(\"optionRemove must name an existing option\")\n\t\t}\n\t\top.Data = name\n\t\treturn removeAttributeViewColumnOption(op)\n\t}\n\tvar config struct {\n\t\tName    string  `json:\"name\"`\n\t\tNewName *string `json:\"newName\"`\n\t\tColor   *string `json:\"color\"`","sourceCodeStart":193,"sourceCodeEnd":229,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/model/attribute_view_key_config.go#L193-L229","documentation":"Option colors must match one of SiYuan's canonical filter/option colors. attrView.FilterColorValue normalizes a submitted color, and if normalization changes it the value was not one of the accepted palette strings, so the update is rejected.","triggerScenarios":"Updating options ('options' setting) or renaming an option ('optionUpdate' with color) where Color is an arbitrary hex string like \"#ff0000\", an out-of-range index, or a non-canonical value.","commonSituations":"Plugin code picking its own palette colors; importer mapping another app's tag colors 1:1; frontend sending a CSS color instead of SiYuan's filter-color value.","solutions":["Use one of the accepted option/filter color values (the palette shown in the SiYuan field editor)","Drop the color field so the default/normalized color is applied","Normalize via the same FilterColorValue logic client-side before sending"],"exampleFix":"// before\n{\"name\":\"Todo\",\"color\":\"#e54545\"}\n// after\n{\"name\":\"Todo\",\"color\":\"4\"}","handlingStrategy":"validation","validationCode":"const ALLOWED_COLORS = new Set([\"\",\"1\",\"2\",\"3\",\"4\",\"5\",\"6\",\"7\",\"8\",\"9\",\"10\",\"11\",\"12\",\"13\"]);\nif (!ALLOWED_COLORS.has(option.color)) throw new Error(`unsupported option color: ${option.color}`);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Only offer the SiYuan palette colors in your UI","Never send raw hex colors for select options"],"tags":["attribute-view","select-options","color"],"backgroundTag":"invalid-enum-value","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"}