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].Index

View on GitHub (pinned to 8641553a1f)

Solutions

  1. Open /storage/inline-styles.json (workspace path data/storage/inline-styles.json) and remove the null element from the builtin.colors array.
  2. If the payload came from an API call or script, fix the serializer to skip empty entries instead of emitting null.
  3. 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

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


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