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
- Inspect MaterialColourSwatchesSnippet.xml and find the <li> elements inside each <section>/<ul>; confirm every swatch li has a class attribute.
- Re-scrape the snippet from the canonical Material Design colour swatches page so the class attributes are restored.
- 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.
- 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
- Treat the snippet schema as a contract: before generation, validate that every swatch <li> has a class attribute.
- When scraping the snippet, drop or skip header <li> rows so only real swatches reach the generator.
- Make the error include the li's name/hex and outer XML so the offending element is immediately identifiable.
- Run a schema check (e.g. all ul > li except first have a class attribute) as a build pre-step.
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
- The input document does not contain a root
- Unable to map foreground color from class {liClass}
- Did not find repository root
AI-assisted analysis of MaterialDesignInXAML/MaterialDesignInXamlToolkit@98edec3a0b (2026-08-13).
Data as JSON: /api/errors/8268e73681e8ae8e.
Report an issue: GitHub.