spectreconsole/spectre.console · error · InvalidOperationException

Color {number} has null name

Error message

Color {number} has null name

What it means

Thrown by ColorModel.ParseAll while reading colors.json: the JSON entry had a number property, but the name property parsed to a null string (the JSON token was null or GetString() returned null). Every color must have a non-null name, so this is treated as malformed data.

Source

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

/// <summary>
/// Parses color data from JSON.
/// </summary>
internal static class ColorParser
{
    /// <summary>
    /// Parses the colors.json file and returns all color models.
    /// </summary>
    public static EquatableArray<ColorModel> ParseAll(string json)
    {
        var document = JsonDocument.Parse(json);
        var colors = new List<ColorModel>();
        var nameCounts = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);

        foreach (var element in document.RootElement.EnumerateArray())
        {
            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));

View on GitHub (pinned to 0acc92fada)

Solutions

  1. Open the bundled colors.json and find the entry whose number matches the message; give it a real name string
  2. Do not hand-edit the shipped colors.json; restore it from the Spectre.Console package
  3. Validate the JSON against the expected schema before replacing the file

Example fix

// before
{ "number": 14, "name": null, "rgb": {"r":0,"g":255,"b":255} }
// after
{ "number": 14, "name": "cyan3", "rgb": {"r":0,"g":255,"b":255} }
Defensive patterns

Strategy: validation

Validate before calling

// Script to scan colors.json for null names before replacing it
using var doc = JsonDocument.Parse(File.ReadAllText("colors.json"));
foreach (var e in doc.RootElement.EnumerateArray())
{
    if (e.GetProperty("name").ValueKind == JsonValueKind.Null)
        Console.Error.WriteLine($"color {e.GetProperty("number").GetInt32()} has null name");
}

Prevention

When it happens

Trigger: A colors.json array element contains "name": null or omits a usable string value for name while having a valid number.

Common situations: Hand-editing colors.json and leaving a null name; a downstream fork of the color data with a typo; schema drift between the generator and the data file.

Related errors


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