siyuan-note/siyuan · error

attribute view custom color index

Error message

attribute view custom color index [%d] is out of range [%d, %d]

What it means

normalizeAttributeViewCustomColor validates that each custom color's Index lies within the inclusive range [CustomColorMinIndex, CustomColorMaxIndex]. An index outside this range cannot be represented in the palette and is rejected with this error naming the offending index and the allowed bounds.

Solutions

  1. Clamp or reassign the index to a value within [CustomColorMinIndex, CustomColorMaxIndex]
  2. Renumber all colors sequentially in-range after import/merge
  3. Check the constants in kernel/av/color.go for the current valid range

Example fix

// before
colors = append(colors, &av.AttributeViewCustomColor{Index: 99, Light: l, Dark: d})
// after
colors = append(colors, &av.AttributeViewCustomColor{Index: av.CustomColorMaxIndex, Light: l, Dark: d})
Defensive patterns

Strategy: validation

Validate before calling

if c.Index < av.CustomColorMinIndex || av.CustomColorMaxIndex < c.Index {
    return fmt.Errorf("index %d out of range", c.Index)
}

Try / catch

if _, err := av.NormalizeAttributeViewCustomColors(colors, true); err != nil {
    if strings.Contains(err.Error(), "is out of range") { renumber(colors) }
}

Prevention

When it happens

Trigger: Calling NormalizeAttributeViewCustomColors (or resolveColor indirectly) with a color whose Index is negative or greater than CustomColorMaxIndex — commonly from hand-edited palette JSON, imported configs, or an off-by-one index counter.

Common situations: Copying an entry and doubling its index; migrating palettes from older versions with different bounds; plugin code computing index from list length that starts at 1 instead of 0 (or vice versa).

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19). Data as JSON: /api/errors/4439c80efa9ac9d9. Report an issue: GitHub.

Appendix: source

Thrown at kernel/av/color.go:132

		indexes[normalized.Index] = struct{}{}
		ret = append(ret, normalized)
	}

	sort.Slice(ret, func(i, j int) bool {
		return ret[i].Index < ret[j].Index
	})
	if nil == ret {
		ret = []*AttributeViewCustomColor{}
	}
	return
}

func normalizeAttributeViewCustomColor(color *AttributeViewCustomColor) (ret *AttributeViewCustomColor, err error) {
	if nil == color {
		return nil, errors.New("attribute view custom color must not be null")
	}
	if color.Index < CustomColorMinIndex || CustomColorMaxIndex < color.Index {
		return nil, fmt.Errorf("attribute view custom color index [%d] is out of range [%d, %d]",
			color.Index, CustomColorMinIndex, CustomColorMaxIndex)
	}

	ret = &AttributeViewCustomColor{Index: color.Index, Hidden: color.Hidden}
	ret.Light, err = normalizeAttributeViewColorTheme(color.Light)
	if nil != err {
		return nil, fmt.Errorf("invalid light theme of attribute view custom color [%d]: %w", color.Index, err)
	}
	ret.Dark, err = normalizeAttributeViewColorTheme(color.Dark)
	if nil != err {
		return nil, fmt.Errorf("invalid dark theme of attribute view custom color [%d]: %w", color.Index, err)
	}
	return
}

func normalizeAttributeViewColorTheme(theme AttributeViewColorTheme) (ret AttributeViewColorTheme, err error) {
	ret.Color = strings.ToLower(strings.TrimSpace(theme.Color))
	ret.BackgroundColor = strings.ToLower(strings.TrimSpace(theme.BackgroundColor))

View on GitHub (pinned to 9f775e8a12)