dotnet/wpf · error · InvalidOperationException
SR.CompositeFont_TooManyFamilyMaps
Error message
SR.CompositeFont_TooManyFamilyMaps
What it means
FamilyMapCollection caps the number of FamilyMap entries at ushort.MaxValue because composite font matching stores family-map indexes in 16-bit skip-list structures. InsertItem (called by Add/Insert) throws InvalidOperationException with CompositeFont_TooManyFamilyMaps when adding one more would reach that limit.
Solutions
- Reduce the number of family maps by coalescing adjacent/overlapping Unicode ranges into fewer maps.
- Cap the generation loop at ushort.MaxValue - 2 maps and log/merge the remainder.
- Split the fallback strategy across multiple FontFamily definitions instead of one collection.
Example fix
// before
for (int cp = 0; cp <= 0x10FFFF; cp++)
familyMaps.Add(new FamilyMap { Unicode = $"U+{cp:X4}-U+{cp:X4}", Target = "Arial" });
// after
const int MaxMaps = ushort.MaxValue - 2;
for (int cp = 0; cp <= 0x10FFFF && familyMaps.Count < MaxMaps; cp++)
familyMaps.Add(new FamilyMap { Unicode = $"U+{cp:X4}-U+{cp:X4}", Target = "Arial" }); Defensive patterns
Strategy: validation
Validate before calling
if (familyMaps.Count >= ushort.MaxValue - 1) throw new InvalidOperationException("Too many family maps; merge Unicode ranges."); Try / catch
try { familyMaps.Add(map); }
catch (InvalidOperationException) { log.Error("Composite font map limit reached (ushort.MaxValue)."); } Prevention
- Coalesce adjacent Unicode ranges to reduce map count
- Enforce a generation-time cap below 65535 maps
- Alert on composite fonts with thousands of maps as a design smell
When it happens
Trigger: Programmatically adding/inserting FamilyMap entries into a FontFamily's FamilyMapCollection (or building a CompositeFont) until Count approaches 65535 — the check is _count + 1 >= ushort.MaxValue.
Common situations: Generating fallback font maps programmatically (e.g. one map per Unicode block or per character), loop-driven configuration builders without a count cap.
Understand the failure class
Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.
Related errors
- SR.Collection_CopyTo_ArrayCannotBeMultidimensional
- SR.Format(SR.CannotConvertType, typeof(FamilyTypeface)…
- SR.Format(SR.Collection_CopyTo_NumberOfElementsExceedsArrayL…
- SR.Format(SR.Collection_CopyTo_IndexGreaterThanOrEqualToArra…
- Collection_CopyTo_ArrayCannotBeMultidimensional
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/ea946c68ab8005dc.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/FamilyMapCollection.cs:255
}
}
#endregion
#region Internal implementation
private int InsertItem(int index, FontFamilyMap item)
{
ArgumentNullException.ThrowIfNull(item);
VerifyChangeable();
// Limit the number of family maps because we use ushort indexes in the skip lists.
// To exceed this limit a user would have to have a separate family maps for almost
// every Unicode value, in which case (since we search sequentially) performance
// would become a problem.
if (_count + 1 >= ushort.MaxValue)
throw new InvalidOperationException(SR.CompositeFont_TooManyFamilyMaps);
// Validate the index.
ArgumentOutOfRangeException.ThrowIfNegative(index);
ArgumentOutOfRangeException.ThrowIfGreaterThan(index, Count);
// PrepareToAddFamilyMap validates the familyName and updates the internal state
// of the CompositeFontInfo object.
_fontInfo.PrepareToAddFamilyMap(item);
// Make room for the new item.
if (_items == null)
{
_items = new FontFamilyMap[InitialCapacity];
}
else if (_count == _items.Length)
{
FontFamilyMap[] items = new FontFamilyMap[_count * 2];
for (int i = 0; i < index; ++i)View on GitHub (pinned to 81131a70a4)