siyuan-note/siyuan · error

attribute view custom color [%d] is still in use by attribut

Error message

attribute view custom color [%d] is still in use by attribute view [%s]

What it means

When updating inline styles, removed custom color entries are checked against workspaceAttributeViewCustomColorUsage, which maps attribute-view IDs to the custom color indexes they still reference. If a color index slated for removal is used by any attribute view, the write is aborted so cells do not lose their color mapping. The error names the offending index and the AV ID that uses it.

Source

Thrown at kernel/model/inline_style.go:271

		Version: InlineStylesVersion,
		Styles:  normalizedStyles,
		Builtin: normalizedBuiltin,
		Order:   normalizeInlineStyleOrder(styles.Order, normalizedStyles),
		AV:      normalizedAV,
	}
	changedCustomColorIndexes := changedAttributeViewCustomColorIndexes(currentAV.Colors, ret.AV.Colors)
	var customColorUsage map[string]map[int]struct{}
	if 0 < len(changedCustomColorIndexes) {
		removedIndexes := removedAttributeViewCustomColorIndexes(currentAV.Colors, ret.AV.Colors)
		customColorUsage, err = workspaceAttributeViewCustomColorUsage(0 < len(removedIndexes))
		if err != nil {
			return nil, false, err
		}
		for _, avID := range sortedAttributeViewUsageIDs(customColorUsage) {
			indexes := customColorUsage[avID]
			for index := range removedIndexes {
				if _, used := indexes[index]; used {
					return nil, false, fmt.Errorf("attribute view custom color [%d] is still in use by attribute view [%s]",
						index, avID)
				}
			}
		}
	}
	data, err := gulu.JSON.MarshalIndentJSON(ret, "", "  ")
	if err != nil {
		return nil, false, fmt.Errorf("marshal inline styles failed: %w", err)
	}
	if maxInlineStylesFileSize < len(data) {
		return nil, false, fmt.Errorf("inline styles file exceeds the %d byte limit", maxInlineStylesFileSize)
	}

	dataPath := inlineStylesPath()
	oldData, readErr := filelock.ReadFile(dataPath)
	if readErr != nil && !os.IsNotExist(readErr) {
		return nil, false, fmt.Errorf("read inline styles failed: %w", readErr)
	}

View on GitHub (pinned to 8641553a1f)

Solutions

  1. Re-add the in-use custom color entry (same index) to the styles payload, or keep the existing palette untouched
  2. Open the named attribute view and change its cells to another color first, then retry the removal
  3. Run workspaceAttributeViewCustomColorUsage yourself to see which indexes are safe to delete before constructing the payload
  4. If the .av references are stale (AV deleted but file remains), clean up the orphaned .av file, then retry

Example fix

// before
styles.Styles = remainingColors // dropped index 3, but AV 20240... still uses it
// after
styles.Styles["3"] = existingColorEntry // keep colors still referenced by attribute views
ret, _, err := SetInlineStyles(styles)
Defensive patterns

Strategy: validation

Validate before calling

usage, err := model.WorkspaceAttributeViewCustomColorUsage(true)
if err != nil { return err }
for idx := range removedIndexes {
    for avID, indexes := range usage {
        if _, used := indexes[idx]; used { return fmt.Errorf("color %d in use by %s", idx, avID) }
    }
}

Try / catch

_, _, err := model.SetInlineStyles(styles)
if err != nil && strings.Contains(err.Error(), "is still in use by attribute view") {
    // parse the index/AV ID from the message, re-add the color or update the AV, then retry
}

Prevention

When it happens

Trigger: Calling SetInlineStyles/SetWorkspaceAVPalette with a styles payload that deletes a custom color entry while some .av file still references that color index in its cell styles.

Common situations: Hand-editing the inline-styles file to prune 'unused' colors without checking attribute views; a script regenerating the palette from scratch while notebooks contain AVs using old indexes; restoring a partial palette backup alongside newer .av files.

Related errors


AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11). Data as JSON: /api/errors/f41a442db268c29d. Report an issue: GitHub.