MaterialDesignInXAML/MaterialDesignInXamlToolkit · error · InvalidDataException

The attribute 'class' was not found

Error message

The attribute 'class' was not found

What it means

CreateJsonColourPair reads each <li> swatch element from the snippet XML and expects it to carry a class= attribute, used to look up the foreground text color (light vs dark) for that swatch. liElement.Attribute("class")?.Value returns null when the attribute is absent, and the ?? coalesce throws InvalidDataException. It fires because the snippet's <li> markup does not match the assumed shape — every swatch li must have class="color ..." for the foreground-mapping table to work.

Source

Thrown at src/MaterialDesignToolkit.ResourceGeneration/Program.cs:238

        var javaScript = string.Format("var swatches={0};", json);

        File.WriteAllText(file, javaScript);
    }

    private static JObject CreateJsonColourPair(XElement liElement)
    {
        var name = liElement.Elements("span").First().Value;
        var hex = liElement.Elements("span").Last().Value;

        var prefix = "Primary";
        if (name.StartsWith("A"))
        {
            prefix = "Secondary";
            name = name.Skip(1).Aggregate("", (current, next) => current + next);
        }

        var liClass = liElement.Attribute("class")?.Value ??
                      throw new InvalidDataException("The attribute 'class' was not found");
        Color foregroundColour;
        if (!ClassNameToForegroundIndex.TryGetValue(liClass, out foregroundColour))
            throw new Exception("Unable to map foreground color from class " + liClass);

        var foreGroundColorHex = string.Format("#{0}{1}{2}",
            ByteToHex(foregroundColour.R),
            ByteToHex(foregroundColour.G),
            ByteToHex(foregroundColour.B));

        var foregroundOpacity = Math.Round(foregroundColour.A / (255.0), 2);

        return new JObject(
            new JProperty("backgroundName", string.Format("{0}{1}", prefix, name)),
            new JProperty("backgroundColour", hex),
            new JProperty("foregroundName", string.Format("{0}{1}Foreground", prefix, name)),
            new JProperty("foregroundColour", foreGroundColorHex),
            new JProperty("foregroundOpacity", foregroundOpacity)
            );

View on GitHub (pinned to 98edec3a0b)

Solutions

  1. Inspect MaterialColourSwatchesSnippet.xml and find the <li> elements inside each <section>/<ul>; confirm every swatch li has a class attribute.
  2. Re-scrape the snippet from the canonical Material Design colour swatches page so the class attributes are restored.
  3. If the missing-class li is a non-swatch row (header, divider), change CreateJsonColourPair to skip li elements that lack both a class and the expected two <span> children rather than throwing.
  4. Make the error message include the offending li's name/hex and outer XML so the bad element is identifiable.

Example fix

// before
var liClass = liElement.Attribute("class")?.Value ??
              throw new InvalidDataException("The attribute 'class' was not found");

// after
var classAttr = liElement.Attribute("class");
if (classAttr is null)
    throw new InvalidDataException(
        $"The attribute 'class' was not found on <li> for swatch '{name}' (hex '{hex}'): {liElement}");
var liClass = classAttr.Value;
Defensive patterns

Strategy: validation

Validate before calling

var classAttr = liElement.Attribute("class");
if (classAttr is null)
    throw new InvalidDataException(
        $"<li> for swatch '{name}' is missing the 'class' attribute: {liElement}");
var liClass = classAttr.Value;

Type guard

static bool LiHasClass(XElement li) => li.Attribute("class") is not null;

// usage before creating the JSON pair
var swatchLis = section.Element("ul")!.Elements("li").Skip(1).Where(LiHasClass);

Try / catch

try
{
    var pair = CreateJsonColourPair(liElement);
}
catch (InvalidDataException ex) when (ex.Message.Contains("'class' was not found"))
{
    // skip non-swatch rows (headers/dividers) instead of aborting the whole JSON build
    Console.Error.WriteLine($"Skipping li without class: {liElement}");
    continue;
}

Prevention

When it happens

Trigger: A particular <li> in MaterialColourSwatchesSnippet.xml has no class attribute — e.g. a header <li>, a newly added accent row, or markup produced by a changed scraping template. The JSON generation path (args containing 'json' or the first positional arg path) iterates sectionElement.Element("ul").Elements("li").Skip(1) and calls CreateJsonColourPair on each, so the first unclassed li trips it.

Common situations: The upstream Material Design colour page changed its HTML structure; the snippet was hand-edited and a class attribute was removed; a new colour was appended without the class attribute; the scrape step was run against a different page variant that omits per-li classes.

Related errors


AI-assisted analysis of MaterialDesignInXAML/MaterialDesignInXamlToolkit@98edec3a0b (2026-08-13). Data as JSON: /api/errors/8268e73681e8ae8e. Report an issue: GitHub.