siyuan-note/siyuan · error
attribute view custom color [%d] is still in use
Error message
attribute view custom color [%d] is still in use
What it means
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.
Source
Thrown at kernel/model/attribute_view.go:8938
if nil == order {
order = oldOrder
}
retainedIndexes := map[int]struct{}{}
for _, color := range colors {
retainedIndexes[color.Index] = struct{}{}
}
usedIndexes := map[int]struct{}{}
for _, index := range attrView.UsedCustomColorIndexes() {
usedIndexes[index] = struct{}{}
}
for _, oldColor := range oldColors {
if nil == oldColor {
continue
}
if _, retained := retainedIndexes[oldColor.Index]; !retained {
if _, used := usedIndexes[oldColor.Index]; used {
return fmt.Errorf("attribute view custom color [%d] is still in use", oldColor.Index)
}
}
}
if err = replaceWorkspaceAVPalette(colors, order); nil != err {
return
}
ReloadAttrView(attrView.ID)
for _, relatedAvID := range av.GetSrcAvIDs(attrView.ID) {
if relatedAvID != attrView.ID {
ReloadAttrView(relatedAvID)
}
}
return
}
func (tx *Transaction) doRemoveAttrViewColOption(operation *Operation) (ret *TxErr) {
err := removeAttributeViewColumnOption(operation)View on GitHub (pinned to 8641553a1f)
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
Example fix
// before replacePalette(newColors) // dropped color index 3 still used // after recolorViewsUsingIndex(3, replacementColor); replacePalette(newColors)
Defensive patterns
Strategy: fallback
Validate before calling
const inUse = getPaletteColorIndexesInUse(); if (newColors.some(c => inUse.has(c.index) === false && wasCustom(c.index))) await recolorViews();
Try / catch
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; } Prevention
- 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
When it happens
Trigger: 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.
Common situations: Cleaning up the palette while views still reference old colors; syncing palettes between workspaces; automated palette pruning without checking usage.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- workspace attribute view palette update must not be null
- workspace attribute view builtin color update must not be nu
- builtin color index [%d] must be between %d and %d
- duplicate workspace attribute view builtin color update [%d]
- attribute view custom color [%d] is still in use by attribut
AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11).
Data as JSON: /api/errors/2eb2d63a7f7815b4.
Report an issue: GitHub.