siyuan-note/siyuan · error
builtin color must not be null
Error message
builtin color must not be null
What it means
The inline-style builtin configuration contains a null entry in its `colors` array. When normalizing `/storage/inline-styles.json`, every builtin color entry must be a fully-populated object with an index and light/dark themes; a null element cannot be validated, so normalizeInlineStyleBuiltin aborts before any settings are applied.
Source
Thrown at kernel/model/inline_style.go:713
if lightColor != darkColor || lightBackground != darkBackground {
return nil, fmt.Errorf("inline style [%s] must use the same fields in light and dark themes", id)
}
ret = append(ret, &InlineStyle{ID: id, Name: name, Hidden: style.Hidden, Light: light, Dark: dark})
}
return ret, nil
}
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].IndexView on GitHub (pinned to 8641553a1f)
Solutions
- Open /storage/inline-styles.json (workspace path data/storage/inline-styles.json) and remove the null element from the builtin.colors array.
- If the payload came from an API call or script, fix the serializer to skip empty entries instead of emitting null.
- If the file is untrusted or badly broken, delete it so the kernel regenerates defaults, then reconfigure builtin colors through the UI.
Example fix
// before (inline-styles.json)
"builtin": { "colors": [ {"index": 1, "light": {...}, "dark": {...}}, null ] }
// after
"builtin": { "colors": [ {"index": 1, "light": {...}, "dark": {...}} ] } Defensive patterns
Strategy: validation
Validate before calling
const colors = config?.builtin?.colors ?? [];
if (colors.some(c => c == null)) {
throw new Error("builtin.colors contains a null entry");
} Type guard
function hasNonNullColors(cfg) {
return Array.isArray(cfg?.builtin?.colors) && cfg.builtin.colors.every(c => c != null);
} Prevention
- Never pre-allocate the colors array with placeholder slots; build it by pushing complete entries.
- Filter out null/undefined entries before serializing inline-styles.json or calling setInlineStylesData.
When it happens
Trigger: Calling setInlineStylesData or loadInlineStyles with a builtin JSON payload where the `builtin.colors` array contains a literal `null` element, e.g. `"colors": [null]` or `"colors": [{...}, null]` in inline-styles.json or an API request body.
Common situations: Hand-edited inline-styles.json where an entry was deleted but the comma/placeholder remained; plugin or script that built the colors array with a fixed size and left unfilled slots as null; JSON produced by code that appends nil pointers to a Go slice of *InlineStyleBuiltinColor.
Related errors
- builtin style must not be null
- inline style must not be null
- duplicate builtin color index [%d]
- invalid builtin style ID [%s]
- duplicate builtin style ID [%s]
AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11).
Data as JSON: /api/errors/959e59e64e7828cb.
Report an issue: GitHub.