MaterialDesignInXAML/MaterialDesignInXamlToolkit · error · Exception

Unable to map foreground color from class {liClass}

Error message

Unable to map foreground color from class {liClass}

What it means

In CreateJsonColourPair, after extracting the li's class attribute, the code looks it up in the fixed dictionary ClassNameToForegroundIndex, whose only keys are 'color', 'color ', 'color dark divide', 'color dark', 'color dark-strong', 'color light-strong', and 'color dark-when-small'. Dictionary.TryGetValue returns false for any class string that is not an EXACT, case-sensitive match, and the code then throws a generic System.Exception (note: not InvalidDataException) with the offending class appended. So this fires when the class attribute value is a new or differently-spaced variant the map does not recognise.

Source

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

    }

    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)
            );
    }

    private static Tuple<string, XDocument> ToResourceDictionary(XElement sectionElement, out bool empty, bool named = false, ColorMode mode = ColorMode.All)

View on GitHub (pinned to 98edec3a0b)

Solutions

  1. Read the liClass value from the error message and add it (with the correct foreground Color) to ClassNameToForegroundIndex.
  2. Before adding a new key, normalise whitespace on both sides: collapse runs of spaces and trim the class string when building the dictionary and when reading liClass, so 'color dark' and 'color dark ' both match.
  3. If the new class is semantically identical to an existing one, alias it to the same Color value rather than inventing a new colour.
  4. Throw InvalidDataException instead of Exception and include the set of known keys in the message to make future misses self-diagnosing.

Example fix

// before
var liClass = liElement.Attribute("class")?.Value;
Color foregroundColour;
if (!ClassNameToForegroundIndex.TryGetValue(liClass, out foregroundColour))
    throw new Exception("Unable to map foreground color from class " + liClass);

// after
var rawClass = liElement.Attribute("class")?.Value ?? "";
// collapse whitespace so 'color  dark' / 'color dark ' still match a canonical key
var liClass = string.Join(" ", rawClass.Split(' ', StringSplitOptions.RemoveEmptyEntries));
Color foregroundColour;
if (!ClassNameToForegroundIndex.TryGetValue(liClass, out foregroundColour))
    throw new InvalidDataException(
        $"Unable to map foreground color from class '{liClass}' (raw='{rawClass}'). " +
        $"Known classes: {string.Join(", ", ClassNameToForegroundIndex.Keys)}");
Defensive patterns

Strategy: validation

Validate before calling

var rawClass = liElement.Attribute("class")?.Value ?? "";
var liClass = string.Join(" ", rawClass.Split(' ', StringSplitOptions.RemoveEmptyEntries));
if (!ClassNameToForegroundIndex.ContainsKey(liClass))
    throw new InvalidDataException(
        $"Unknown swatch class '{liClass}'. Expected one of: {string.Join(", ", ClassNameToForegroundIndex.Keys)}");

Type guard

static readonly HashSet<string> KnownForegroundClasses =
    ClassNameToForegroundIndex.Keys.ToHashSet();

static bool IsKnownForegroundClass(string? raw)
{
    if (raw is null) return false;
    var norm = string.Join(" ", raw.Split(' ', StringSplitOptions.RemoveEmptyEntries));
    return KnownForegroundClasses.Contains(norm);
}

Try / catch

try
{
    /* lookup */
}
catch (Exception ex) when (ex.Message.StartsWith("Unable to map foreground color from class"))
{
    // surface the offending class + the full known-key set, then abort or skip
    Console.Error.WriteLine(ex.Message + " -- known keys: " + string.Join(", ", ClassNameToForegroundIndex.Keys));
    throw;
}

Prevention

When it happens

Trigger: An <li> carries a class attribute whose value is not one of the seven hard-coded keys — e.g. 'color dark-when-large', 'color light', 'color dark' (double space), 'Color dark' (capital C), or any trailing-space variant other than the one 'color ' entry. The message includes the actual liClass so you can see exactly which string failed.

Common situations: The Material Design swatches page introduced a new foreground class (e.g. a responsive variant); the scrape normalised/did not normalise whitespace differently than the map expects; copy-paste introduced a trailing space or different case; an older snippet is paired with newer map keys or vice-versa.

Related errors


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