dotnet/wpf · error · InvalidEnumArgumentException
The value of argument 'unit
Error message
The value of argument 'unit' ({0}) is invalid for Enum type 'TextUnit'. What it means
ITextRangeProvider.ExpandToEnclosingUnit throws InvalidEnumArgumentException when the TextUnit argument is not one of the defined values (Character/Word/Line/Paragraph/Page/Document). The switch has no handler for unknown unit values.
Solutions
- Validate that Enum.IsDefined(typeof(TextUnit), value) before calling ExpandToEnclosingUnit.
- Only pass literal TextUnit enum members, never raw ints.
- Catch InvalidEnumArgumentException at the boundary and map unknown units to a supported one (e.g. Document).
- Upgrade/reference the matching UIAutomation assemblies so the TextUnit enum values line up.
Example fix
// before var unit = (TextUnit)rawInt; range.ExpandToEnclosingUnit(unit); // InvalidEnumArgumentException // after var unit = Enum.IsDefined(typeof(TextUnit), rawInt) ? (TextUnit)rawInt : TextUnit.Document; range.ExpandToEnclosingUnit(unit);
Defensive patterns
Strategy: type-guard
Validate before calling
if (!Enum.IsDefined(typeof(TextUnit), value)) throw new ArgumentOutOfRangeException(nameof(value));
Type guard
static bool IsValidTextUnit(int v) => v >= (int)TextUnit.Character && v <= (int)TextUnit.Document && Enum.IsDefined(typeof(TextUnit), v);
Try / catch
try { range.ExpandToEnclosingUnit(unit); }
catch (InvalidEnumArgumentException) { range.ExpandToEnclosingUnit(TextUnit.Document); } Prevention
- Never cast unvalidated ints to TextUnit.
- Use Enum.IsDefined before conversions.
- Pin UIAutomation assembly versions so enum values agree.
When it happens
Trigger: Calling ExpandToEnclosingUnit (or code paths that call it) with a TextUnit value cast from an unvalidated int, or a TextUnit from a newer/other framework version not recognized by this switch.
Common situations: Casting raw int attribute values from config or interop to TextUnit; handling a protocol payload whose unit field is out of the enum's range; copying constants from documentation that don't match this API's enum.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- Win32 edit control cannot have a child element.
- Animation_UnrecognizedHandoffBehavior
- Character offset not valid in TextRange.
- InvalidEnumArgumentException for value (TextTrimming)
- InvalidEnumArgumentException("mode", (int)mode…
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/26e78e2a4df286a2.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/UIAutomation/UIAutomationClientSideProviders/MS/Internal/AutomationProxies/WindowsEditBoxRange.cs:174
// move start left until we reach a paragraph boundary.
for (; !AtParagraphBoundary(text, Start); Start--);
// move end right until we reach a paragraph boundary (different from Start).
End = Math.Min(Math.Max(End, Start + 1), text.Length);
for (; !AtParagraphBoundary(text, End); End++);
}
break;
case TextUnit.Format:
case TextUnit.Page:
case TextUnit.Document:
MoveTo(0, _provider.GetTextLength());
break;
//break;
default:
throw new System.ComponentModel.InvalidEnumArgumentException("unit", (int)unit, typeof(TextUnit));
}
}
ITextRangeProvider ITextRangeProvider.FindAttribute(int attributeId, object val, bool backwards)
{
AutomationTextAttribute attribute = AutomationTextAttribute.LookupById(attributeId);
// generic controls are plain text so if the attribute matches then it matches over the whole range.
// To workaround the conversion that Marshaling of COM-interop did.
object targetAttribute = GetAttributeValue(attribute);
if (targetAttribute is Enum)
{
targetAttribute = (int)targetAttribute;
}
return val.Equals(targetAttribute) ? new WindowsEditBoxRange(_provider, Start, End) : null;
}
View on GitHub (pinned to 81131a70a4)