siyuan-note/siyuan · error

builtin style must not be null

Error message

builtin style must not be null

What it means

A null entry was found in the builtin `styles` array. Builtin styles are the fixed set (error, warning, info, success); each entry must be a non-null object so its ID and light/dark themes can be validated. A null element cannot be normalized and aborts the whole builtin configuration load.

Source

Thrown at kernel/model/inline_style.go:737

		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")
		}
		id := strings.TrimSpace(style.ID)
		if _, valid := builtinStyleOrder[id]; !valid {
			return nil, fmt.Errorf("invalid builtin style ID [%s]", id)
		}
		if _, exists := styleIDs[id]; exists {
			return nil, fmt.Errorf("duplicate builtin style ID [%s]", id)
		}
		styleIDs[id] = struct{}{}

		light, dark, err := normalizeInlineStyleThemePair(style.Light, style.Dark, "builtin style ["+id+"]")
		if err != nil {
			return nil, err
		}
		ret.Styles = append(ret.Styles, &InlineStyleBuiltinStyle{ID: id, Light: light, Dark: dark})
	}
	sort.Slice(ret.Styles, func(i, j int) bool {
		return builtinStyleOrder[ret.Styles[i].ID] < builtinStyleOrder[ret.Styles[j].ID]

View on GitHub (pinned to 8641553a1f)

Solutions

  1. Remove the null element from the builtin.styles array in /storage/inline-styles.json or the API payload.
  2. Fix the generating code to omit empty entries rather than emitting null.
  3. If the file is corrupted beyond repair, delete it so defaults are regenerated and reconfigure via the settings UI.

Example fix

// before
"styles": [ {"id": "error", ...}, null ]
// after
"styles": [ {"id": "error", ...} ]
Defensive patterns

Strategy: validation

Validate before calling

const styles = config?.builtin?.styles ?? [];
if (styles.some(s => s == null)) {
  throw new Error("builtin.styles contains a null entry");
}

Type guard

function hasNonNullStyles(cfg) {
  return Array.isArray(cfg?.builtin?.styles) && cfg.builtin.styles.every(s => s != null);
}

Prevention

When it happens

Trigger: setInlineStylesData or loadInlineStyles with builtin.styles containing a literal `null`, e.g. `"styles": [{"id": "error", ...}, null]`.

Common situations: Hand-edited inline-styles.json with a leftover placeholder; Go/JS code that pre-allocates a 4-element array and fills only some slots; JSON round-trip that serialized missing entries as null.

Related errors


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