siyuan-note/siyuan · error
duplicate workspace attribute view builtin color update [%d]
Error message
duplicate workspace attribute view builtin color update [%d]
What it means
SetWorkspaceAVPalette tracks already-seen builtin color indexes in updatedIndexes while iterating update.BuiltinColors. If two patches target the same index the update is ambiguous, so it fails with this error instead of applying the patches in undocumented order.
Source
Thrown at kernel/model/inline_style.go:198
return nil, false, errors.New("workspace attribute view palette update must not be null")
}
current, err := loadInlineStyles()
if err != nil {
return nil, false, err
}
currentAV := current.AV
current.AV = &InlineStyleAV{Colors: update.Colors, Order: update.Order}
updatedIndexes := map[int]struct{}{}
for _, patch := range update.BuiltinColors {
if patch == nil {
return nil, false, errors.New("workspace attribute view builtin color update must not be null")
}
if patch.Index < minBuiltinColorIndex || neutralAVColorIndex < patch.Index {
return nil, false, fmt.Errorf("builtin color index [%d] must be between %d and %d", patch.Index,
minBuiltinColorIndex, neutralAVColorIndex)
}
if _, duplicated := updatedIndexes[patch.Index]; duplicated {
return nil, false, fmt.Errorf("duplicate workspace attribute view builtin color update [%d]", patch.Index)
}
updatedIndexes[patch.Index] = struct{}{}
filtered := current.Builtin.Colors[:0]
for _, color := range current.Builtin.Colors {
if color.Index != patch.Index {
filtered = append(filtered, color)
}
}
current.Builtin.Colors = filtered
if patch.Customized {
current.Builtin.Colors = append(current.Builtin.Colors, &InlineStyleBuiltinColor{
Index: patch.Index,
Light: patch.Light,
Dark: patch.Dark,
})
}
filteredHidden := current.Builtin.Hidden.AV[:0]
for _, index := range current.Builtin.Hidden.AV {View on GitHub (pinned to 8641553a1f)
Solutions
- Deduplicate BuiltinColors by Index (last-wins or first-wins per your intent) before calling SetWorkspaceAVPalette
- Build the patch list as a map[int]*InlineStyleBuiltinColorPatch during collection, then convert to a slice
- Fix the caller's merge/retry logic so the same index is never appended twice
Example fix
// before: duplicate indexes appended
patches = append(patches, &model.InlineStyleBuiltinColorPatch{Index: 3, Color: red})
patches = append(patches, &model.InlineStyleBuiltinColorPatch{Index: 3, Color: blue}) // duplicate
// after: dedupe by index, last wins
byIndex := map[int]*model.InlineStyleBuiltinColorPatch{}
byIndex[3] = &model.InlineStyleBuiltinColorPatch{Index: 3, Color: red}
byIndex[3] = &model.InlineStyleBuiltinColorPatch{Index: 3, Color: blue}
for _, p := range byIndex { patches = append(patches, p) } Defensive patterns
Strategy: validation
Validate before calling
seen := map[int]bool{}
for _, p := range patches {
if seen[p.Index] { return fmt.Errorf("duplicate patch index %d", p.Index) }
seen[p.Index] = true
} Try / catch
_, _, err := model.SetWorkspaceAVPalette(update)
if err != nil && strings.Contains(err.Error(), "duplicate workspace attribute view builtin color") {
// deduplicate by index and retry
} Prevention
- Collect patches in a map[int]Patch and convert to a slice at the end
- Deduplicate accumulated edits before saving the palette
- Make retry/merge logic idempotent per index
When it happens
Trigger: Passing a WorkspaceAVPaletteUpdate whose BuiltinColors slice contains two or more patches with the same Index value — the second occurrence triggers the duplicate check in the loop.
Common situations: Frontend accumulates color edits without deduplicating by index before saving; a plugin merges multiple patch sets naively with append; retry logic appends a patch twice.
Related errors
- workspace attribute view builtin color update must not be nu
- builtin color index [%d] must be between %d and %d
- duplicated attribute view custom color index [%d]
- attribute view custom color [%d] is still in use
- workspace attribute view palette update must not be null
AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11).
Data as JSON: /api/errors/4bf0fe879a938782.
Report an issue: GitHub.