{"record":{"id":"d72d7524f052554d","repo":"siyuan-note/siyuan","slug":"workspace-attribute-view-builtin-color-update-must","errorCode":null,"errorMessage":"workspace attribute view builtin color update must not be null","messagePattern":"workspace attribute view builtin color update must not be null","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/inline_style.go","lineNumber":191,"sourceCode":"// SetWorkspaceAVPalette 只更新数据库颜色配置，保留其他窗口可能同时修改的行级样式设置。\nfunc SetWorkspaceAVPalette(update *WorkspaceAVPaletteUpdate) (ret *InlineStyles, changed bool, err error) {\n\twaitForSyncingStorages()\n\tinlineStylesLock.Lock()\n\tdefer inlineStylesLock.Unlock()\n\n\tif update == nil {\n\t\treturn nil, false, errors.New(\"workspace attribute view palette update must not be null\")\n\t}\n\tcurrent, err := loadInlineStyles()\n\tif err != nil {\n\t\treturn nil, false, err\n\t}\n\tcurrentAV := current.AV\n\tcurrent.AV = &InlineStyleAV{Colors: update.Colors, Order: update.Order}\n\tupdatedIndexes := map[int]struct{}{}\n\tfor _, patch := range update.BuiltinColors {\n\t\tif patch == nil {\n\t\t\treturn nil, false, errors.New(\"workspace attribute view builtin color update must not be null\")\n\t\t}\n\t\tif patch.Index < minBuiltinColorIndex || neutralAVColorIndex < patch.Index {\n\t\t\treturn nil, false, fmt.Errorf(\"builtin color index [%d] must be between %d and %d\", patch.Index,\n\t\t\t\tminBuiltinColorIndex, neutralAVColorIndex)\n\t\t}\n\t\tif _, duplicated := updatedIndexes[patch.Index]; duplicated {\n\t\t\treturn nil, false, fmt.Errorf(\"duplicate workspace attribute view builtin color update [%d]\", patch.Index)\n\t\t}\n\t\tupdatedIndexes[patch.Index] = struct{}{}\n\t\tfiltered := current.Builtin.Colors[:0]\n\t\tfor _, color := range current.Builtin.Colors {\n\t\t\tif color.Index != patch.Index {\n\t\t\t\tfiltered = append(filtered, color)\n\t\t\t}\n\t\t}\n\t\tcurrent.Builtin.Colors = filtered\n\t\tif patch.Customized {\n\t\t\tcurrent.Builtin.Colors = append(current.Builtin.Colors, &InlineStyleBuiltinColor{","sourceCodeStart":173,"sourceCodeEnd":209,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/8641553a1f07374001902d3ce773285db1292b2d/kernel/model/inline_style.go#L173-L209","documentation":"Within SetWorkspaceAVPalette, update.BuiltinColors may contain per-index patch entries. A nil entry in that slice cannot be applied, so the function aborts the whole palette update with this error rather than silently skipping part of the patch list.","triggerScenarios":"Passing a WorkspaceAVPaletteUpdate whose BuiltinColors slice contains a nil element, e.g. &WorkspaceAVPaletteUpdate{BuiltinColors: []*InlineStyleBuiltinColorPatch{nil}} from an API caller or test.","commonSituations":"Frontend serializes an array with holes/sparse entries that decode to nil pointers; a plugin builds the patch list dynamically and appends nil on a failed lookup; hand-written JSON like \"builtinColors\": [null].","solutions":["Filter out nil entries from BuiltinColors before calling SetWorkspaceAVPalette","Fix the caller (frontend/plugin) to never emit null elements in the builtinColors JSON array","In Go, use a typed non-nil slice when constructing the update"],"exampleFix":"// before: patch list contains a nil entry\nupdate := &model.WorkspaceAVPaletteUpdate{\n\tBuiltinColors: []*model.InlineStyleBuiltinColorPatch{patch1, nil},\n}\nmodel.SetWorkspaceAVPalette(update) // error\n// after: filter nils first\npatches := patches[:0]\nfor _, p := range patches {\n\tif p != nil { patches = append(patches, p) }\n}\nupdate.BuiltinColors = patches","handlingStrategy":"type-guard","validationCode":"for i, p := range patches {\n\tif p == nil { return fmt.Errorf(\"builtin color patch %d is nil\", i) }\n}","typeGuard":"func validPatches(ps []*model.InlineStyleBuiltinColorPatch) bool {\n\tfor _, p := range ps { if p == nil { return false } }\n\treturn true\n}","tryCatchPattern":"_, _, err := model.SetWorkspaceAVPalette(update)\nif err != nil && strings.Contains(err.Error(), \"builtin color update must not be null\") {\n\t// filter nils and retry\n}","preventionTips":["Filter nil entries out of BuiltinColors before calling the API","Never emit null elements in the builtinColors JSON array","Build patch lists with explicit non-nil constructors"],"tags":["attribute-view","palette","builtin-colors","nil-argument"],"backgroundTag":"null-argument","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"}