siyuan-note/siyuan · error
duplicate builtin color index [%d]
Error message
duplicate builtin color index [%d]
What it means
Two builtin color entries declare the same `index`. Builtin color indexes are unique identifiers for the 14 palette slots, so normalizeInlineStyleBuiltin rejects duplicates to keep palette order, hiding configuration (builtin.Hidden.Color/AV), and AV color rendering unambiguous.
Source
Thrown at kernel/model/inline_style.go:720
}
func normalizeInlineStyleBuiltin(builtin *InlineStyleBuiltin) (ret *InlineStyleBuiltin, err error) {
ret = newEmptyInlineStyleBuiltin()
if builtin == nil {
return ret, nil
}
colorIndexes := make(map[int]struct{}, len(builtin.Colors))
for _, color := range builtin.Colors {
if color == nil {
return nil, errors.New("builtin color must not be null")
}
if color.Index < minBuiltinColorIndex || neutralAVColorIndex < color.Index {
return nil, fmt.Errorf("builtin color index [%d] must be between %d and %d", color.Index,
minBuiltinColorIndex, neutralAVColorIndex)
}
if _, exists := colorIndexes[color.Index]; exists {
return nil, fmt.Errorf("duplicate builtin color index [%d]", color.Index)
}
colorIndexes[color.Index] = struct{}{}
light, dark, err := normalizeInlineStyleThemePair(color.Light, color.Dark, fmt.Sprintf("builtin color [%d]", color.Index))
if err != nil {
return nil, err
}
ret.Colors = append(ret.Colors, &InlineStyleBuiltinColor{Index: color.Index, Light: light, Dark: dark})
}
sort.Slice(ret.Colors, func(i, j int) bool {
return ret.Colors[i].Index < ret.Colors[j].Index
})
styleIDs := make(map[string]struct{}, len(builtin.Styles))
for _, style := range builtin.Styles {
if style == nil {
return nil, errors.New("builtin style must not be null")
}View on GitHub (pinned to 8641553a1f)
Solutions
- Find the duplicated index in builtin.colors of inline-styles.json and renumber one entry to an unused index between 1 and 14.
- If both entries are unintended duplicates of the same palette slot, delete the redundant entry.
- Validate the array programmatically (collect indexes into a set) before saving the config or sending it via setInlineStylesData.
Example fix
// before
[{"index": 3, ...}, {"index": 3, ...}]
// after
[{"index": 3, ...}, {"index": 4, ...}] Defensive patterns
Strategy: validation
Validate before calling
const seen = new Set();
for (const c of config.builtin.colors) {
if (seen.has(c.index)) throw new Error(`duplicate builtin color index ${c.index}`);
seen.add(c.index);
} Prevention
- When cloning a color entry to create a new one, always update its index first.
- Run the duplicate-index set check as part of any script that merges or generates inline style configs.
When it happens
Trigger: setInlineStylesData or loadInlineStyles with builtin.colors containing two entries with the same index value, e.g. two entries both with `"index": 5`.
Common situations: Copy-pasting a color entry and forgetting to change its index; merging configuration files from two workspaces; a script cloning the last array element to add a new color.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- duplicate builtin style ID [%s]
- builtin color must not be null
- builtin style must not be null
- invalid builtin style ID [%s]
- %s must define light and dark themes
AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11).
Data as JSON: /api/errors/4ab319fc39db3d30.
Report an issue: GitHub.