spectreconsole/spectre.console · error · InvalidOperationException

Color {number} has null alias

Error message

Color {number} has null alias

What it means

Thrown by ColorModel.ParseAll while iterating an entry's aliases array: one alias element parsed to null via GetString(). Each alias must be a real string, so a null alias aborts parsing with the offending color number in the message.

Source

Thrown at src/Spectre.Console.SourceGenerator/Colors/ColorModel.cs:52

            var number = element.GetProperty("number").GetInt32();
            var name = element.GetProperty("name").GetString()
                ?? throw new InvalidOperationException($"Color {number} has null name");
            var rgb = element.GetProperty("rgb");
            var r = (byte)rgb.GetProperty("r").GetInt32();
            var g = (byte)rgb.GetProperty("g").GetInt32();
            var b = (byte)rgb.GetProperty("b").GetInt32();

            // Track name occurrences for deduplication
            var uniqueName = GetUniqueName(name, nameCounts);
            colors.Add(new ColorModel(number, uniqueName, r, g, b, IsAlias: false));

            // Process aliases
            if (element.TryGetProperty("aliases", out var aliases))
            {
                foreach (var alias in aliases.EnumerateArray())
                {
                    var aliasName = alias.GetString()
                        ?? throw new InvalidOperationException($"Color {number} has null alias");
                    var uniqueAliasName = GetUniqueName(aliasName, nameCounts);
                    colors.Add(new ColorModel(number, uniqueAliasName, r, g, b, IsAlias: true));
                }
            }
        }

        return new EquatableArray<ColorModel>(colors);
    }

    private static string GetUniqueName(string name, Dictionary<string, int> nameCounts)
    {
        if (!nameCounts.TryGetValue(name, out var count))
        {
            nameCounts[name] = 1;
            return name;
        }

        nameCounts[name] = count + 1;

View on GitHub (pinned to 0acc92fada)

Solutions

  1. Locate the color by the number in the message and inspect its aliases array
  2. Remove null entries or replace them with real alias strings
  3. Restore colors.json from the package if unsure

Example fix

// before
{ "number": 1, "aliases": ["red", null] }
// after
{ "number": 1, "aliases": ["red", "maroon"] }
Defensive patterns

Strategy: validation

Validate before calling

// Scan colors.json aliases for null elements before replacing the file
using var doc = JsonDocument.Parse(File.ReadAllText("colors.json"));
foreach (var e in doc.RootElement.EnumerateArray())
{
    if (e.TryGetProperty("aliases", out var a))
        foreach (var alias in a.EnumerateArray())
            if (alias.ValueKind == JsonValueKind.Null)
                Console.Error.WriteLine($"color {e.GetProperty("number").GetInt32()} has null alias");
}

Prevention

When it happens

Trigger: A colors.json entry has an "aliases" array containing a null element (e.g. "aliases": [null] or "aliases": ["good", null]).

Common situations: Editing alias lists and leaving a trailing null; tooling that serializes sparse arrays; schema drift.

Related errors


AI-assisted analysis of spectreconsole/spectre.console@0acc92fada (2026-08-13). Data as JSON: /api/errors/c46bbb54f80db743. Report an issue: GitHub.