{"record":{"id":"d58892a4d5909f85","repo":"siyuan-note/siyuan","slug":"attribute-view-custom-colors-count-exceeds-the-d","errorCode":null,"errorMessage":"attribute view custom colors count exceeds the %d item limit","messagePattern":"attribute view custom colors count exceeds the (.+?) item limit","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/av/color.go","lineNumber":96,"sourceCode":"// UnmarshalJSON 忽略外部输入中的派生颜色，派生颜色只能由内核根据数据库调色板生成。\nfunc (value *ValueSelect) UnmarshalJSON(data []byte) error {\n\tdecoded := struct {\n\t\tContent string `json:\"content\"`\n\t\tColor   string `json:\"color\"`\n\t}{}\n\tif err := json.Unmarshal(data, &decoded); nil != err {\n\t\treturn err\n\t}\n\tvalue.Content = decoded.Content\n\tvalue.Color = decoded.Color\n\tvalue.ResolvedColor = nil\n\treturn nil\n}\n\n// NormalizeAttributeViewCustomColors 校验并规范化数据库自定义颜色。\nfunc NormalizeAttributeViewCustomColors(colors []*AttributeViewCustomColor, strict bool) (ret []*AttributeViewCustomColor, err error) {\n\tif strict && MaxCustomColors < len(colors) {\n\t\treturn nil, fmt.Errorf(\"attribute view custom colors count exceeds the %d item limit\", MaxCustomColors)\n\t}\n\n\tindexes := map[int]struct{}{}\n\tfor _, color := range colors {\n\t\tnormalized, normalizeErr := normalizeAttributeViewCustomColor(color)\n\t\tif nil != normalizeErr {\n\t\t\tif strict {\n\t\t\t\treturn nil, normalizeErr\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\t\tif _, ok := indexes[normalized.Index]; ok {\n\t\t\tif strict {\n\t\t\t\treturn nil, fmt.Errorf(\"duplicated attribute view custom color index [%d]\", normalized.Index)\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\t\tindexes[normalized.Index] = struct{}{}","sourceCodeStart":78,"sourceCodeEnd":114,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/8641553a1f07374001902d3ce773285db1292b2d/kernel/av/color.go#L78-L114","documentation":"NormalizeAttributeViewCustomColors returns this error in strict mode when the caller supplies more custom colors than MaxCustomColors allows (CustomColorMaxIndex 78 - CustomColorMinIndex 15 + 1 = 64). The limit exists because each custom color occupies one reserved index slot in the color space.","triggerScenarios":"Calling av.NormalizeAttributeViewCustomColors(colors, true) with len(colors) > 64; setAttrViewCustomColors or palette decoding paths (decodeHistoricalWorkspacePalette, customColorPalette) receiving an oversized palette.","commonSituations":"Importing/pasting a palette from another workspace or tool with more entries than the reserved index range; a migration script enumerating indexes without knowing the 15..78 bound; merging two color configurations.","solutions":["Trim the color list to at most av.MaxCustomColors (64) entries before normalizing in strict mode.","Pass strict=false if best-effort normalization (dedupe/trim silently) is acceptable — non-strict mode drops extras instead of erroring.","Assign colors to the reserved index range [CustomColorMinIndex 15, CustomColorMaxIndex 78]; if the palette is larger, remap to built-in colors instead of custom slots.","Merge duplicates first (same index/light/dark) to reduce the count before calling."],"exampleFix":"// before\nret, err := av.NormalizeAttributeViewCustomColors(colors, true) // 80 colors -> error\n\n// after\nif len(colors) > av.MaxCustomColors {\n\tcolors = colors[:av.MaxCustomColors]\n}\nret, err := av.NormalizeAttributeViewCustomColors(colors, true)","handlingStrategy":"validation","validationCode":"func withinColorLimit(colors []*av.AttributeViewCustomColor) bool {\n\treturn len(colors) <= av.MaxCustomColors // 64\n}","typeGuard":null,"tryCatchPattern":"if _, err := av.NormalizeAttributeViewCustomColors(colors, true); err != nil && strings.Contains(err.Error(), \"count exceeds\") {\n\tcolors = colors[:av.MaxCustomColors]\n}","preventionTips":["Trim imported palettes to av.MaxCustomColors entries","Use strict=false when best-effort trimming is acceptable","Merge duplicate colors before counting"],"tags":["attribute-view","custom-color","limit-exceeded","validation","siyuan-kernel"],"backgroundTag":"payload-too-large","analyzedSha":"8641553a1f07374001902d3ce773285db1292b2d","analyzedAt":"2026-09-11T16:08:28.414Z","contentChangedAt":"2026-09-11T16:08:28.414Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}