{"record":{"id":"2eb2d63a7f7815b4","repo":"siyuan-note/siyuan","slug":"attribute-view-custom-color-d-is-still-in-use","errorCode":null,"errorMessage":"attribute view custom color [%d] is still in use","messagePattern":"attribute view custom color \\[(.+?)\\] is still in use","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/attribute_view.go","lineNumber":8938,"sourceCode":"\tif nil == order {\n\t\torder = oldOrder\n\t}\n\n\tretainedIndexes := map[int]struct{}{}\n\tfor _, color := range colors {\n\t\tretainedIndexes[color.Index] = struct{}{}\n\t}\n\tusedIndexes := map[int]struct{}{}\n\tfor _, index := range attrView.UsedCustomColorIndexes() {\n\t\tusedIndexes[index] = struct{}{}\n\t}\n\tfor _, oldColor := range oldColors {\n\t\tif nil == oldColor {\n\t\t\tcontinue\n\t\t}\n\t\tif _, retained := retainedIndexes[oldColor.Index]; !retained {\n\t\t\tif _, used := usedIndexes[oldColor.Index]; used {\n\t\t\t\treturn fmt.Errorf(\"attribute view custom color [%d] is still in use\", oldColor.Index)\n\t\t\t}\n\t\t}\n\t}\n\n\tif err = replaceWorkspaceAVPalette(colors, order); nil != err {\n\t\treturn\n\t}\n\tReloadAttrView(attrView.ID)\n\tfor _, relatedAvID := range av.GetSrcAvIDs(attrView.ID) {\n\t\tif relatedAvID != attrView.ID {\n\t\t\tReloadAttrView(relatedAvID)\n\t\t}\n\t}\n\treturn\n}\n\nfunc (tx *Transaction) doRemoveAttrViewColOption(operation *Operation) (ret *TxErr) {\n\terr := removeAttributeViewColumnOption(operation)","sourceCodeStart":8920,"sourceCodeEnd":8956,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/8641553a1f07374001902d3ce773285db1292b2d/kernel/model/attribute_view.go#L8920-L8956","documentation":"When replacing the workspace attribute-view color palette, custom colors that are still referenced by remaining attribute view indexes cannot be removed. If an old custom color's index is not retained (not in the new palette) but is still used by some view, the kernel aborts with this error naming the color index.","triggerScenarios":"Calling the palette/custom-colors update API (replaceWorkspaceAVPalette path) with a new color list that drops a custom color whose index is still assigned to cells in some attribute view.","commonSituations":"Cleaning up the palette while views still reference old colors; syncing palettes between workspaces; automated palette pruning without checking usage.","solutions":["Keep the in-use custom color in the new palette (retain its index)","Re-color the views/cells using that index first, then retry the palette update","Query which attribute views use the color index and update them before pruning"],"exampleFix":"// before\nreplacePalette(newColors) // dropped color index 3 still used\n// after\nrecolorViewsUsingIndex(3, replacementColor); replacePalette(newColors)","handlingStrategy":"fallback","validationCode":"const inUse = getPaletteColorIndexesInUse(); if (newColors.some(c => inUse.has(c.index) === false && wasCustom(c.index))) await recolorViews();","typeGuard":null,"tryCatchPattern":"try { await setPalette(colors, order); } catch (e) { const m = String(e).match(/color \\[(\\d+)\\] is still in use/); if (m) { await recolorIndex(Number(m[1])); await setPalette(colors, order); } else throw e; }","preventionTips":["Audit view cell color usage before pruning the palette","Retain colors in use; only remove unused custom colors","Test palette changes against views that reference old colors"],"tags":["attribute-view","palette","conflict"],"backgroundTag":"invalid-state-transition","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"}