siyuan-note/siyuan · error
%s must define light and dark themes
Error message
%s must define light and dark themes
What it means
A theme pair for a builtin color or builtin style is missing one of its two halves: either `light` or `dark` is null. Builtin entries must always supply both themes so the editor can render consistently when the appearance theme mode switches. The description in the message identifies which entry (e.g. "builtin color [3]" or "builtin style [warning]").
Source
Thrown at kernel/model/inline_style.go:793
func normalizeInlineStyleAV(palette *InlineStyleAV, strict bool) (ret *InlineStyleAV, err error) {
ret = newEmptyInlineStyleAV()
if palette == nil {
return ret, nil
}
colors, err := av.NormalizeAttributeViewCustomColors(palette.Colors, strict)
if err != nil {
return nil, err
}
ret.Colors = colors
ret.Order = av.NormalizeAttributeViewColorOrder(palette.Order, colors)
return ret, nil
}
func normalizeInlineStyleThemePair(light, dark *InlineStyleTheme, description string) (normalizedLight,
normalizedDark *InlineStyleTheme, err error) {
if light == nil || dark == nil {
return nil, nil, fmt.Errorf("%s must define light and dark themes", description)
}
if normalizedLight, err = normalizeInlineStyleTheme(light); err != nil {
return nil, nil, fmt.Errorf("invalid light theme of %s: %w", description, err)
}
if normalizedDark, err = normalizeInlineStyleTheme(dark); err != nil {
return nil, nil, fmt.Errorf("invalid dark theme of %s: %w", description, err)
}
lightColor, lightBackground := normalizedLight.Color != "", normalizedLight.BackgroundColor != ""
darkColor, darkBackground := normalizedDark.Color != "", normalizedDark.BackgroundColor != ""
if !lightColor && !lightBackground {
return nil, nil, fmt.Errorf("%s must define color or backgroundColor", description)
}
if lightColor != darkColor || lightBackground != darkBackground {
return nil, nil, fmt.Errorf("%s must use the same fields in light and dark themes", description)
}
return normalizedLight, normalizedDark, nil
}
View on GitHub (pinned to 8641553a1f)
Solutions
- Add the missing `light` or `dark` theme object to the entry identified by the message prefix.
- If both modes should look identical, still provide both objects with the same color/backgroundColor values.
- Ensure the writing code does not use omitempty-style behavior on light/dark theme fields.
Example fix
// before
{"index": 2, "light": {"backgroundColor": "#eeeeee"}}
// after
{"index": 2, "light": {"backgroundColor": "#eeeeee"}, "dark": {"backgroundColor": "#222222"}} Defensive patterns
Strategy: validation
Validate before calling
for (const entry of entries) { // builtin colors and styles
if (!entry.light || !entry.dark) {
throw new Error(`${describe(entry)} must define light and dark themes`);
}
} Type guard
function hasThemePair(entry) {
return entry.light != null && entry.dark != null;
} Prevention
- Always write both theme objects even when light and dark are identical.
- Avoid omitempty-style serialization on light/dark theme fields.
When it happens
Trigger: setInlineStylesData or loadInlineStyles with a builtin color/style entry that omits the `light` or `dark` key, or sets it to null, passed into normalizeInlineStyleThemePair via normalizeInlineStyleBuiltin.
Common situations: JSON hand-authored with only the current theme mode filled in; a serializer with `omitempty` dropping an empty theme object; partially completed edit of inline-styles.json.
Understand the failure class
Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.
Related errors
- %s must define color or backgroundColor
- builtin color must not be null
- duplicate builtin color index [%d]
- builtin style must not be null
- invalid builtin style ID [%s]
AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11).
Data as JSON: /api/errors/f656bd99d14e125c.
Report an issue: GitHub.