dotnet/wpf · error · ArgumentOutOfRangeException
ArgumentOutOfRangeException(nameof(characterHit))
Error message
ArgumentOutOfRangeException(nameof(characterHit))
What it means
GetDistanceFromCaretCharacterHit throws ArgumentOutOfRangeException when the CharacterHit's FirstCharacterIndex is negative or greater than the GlyphRun's CodepointCount. Only character hits that fall inside the run's codepoint range are meaningful for caret distance measurement. The method checks this right after confirming the run is fully initialized.
Solutions
- Clamp or validate characterHit.FirstCharacterIndex to [0, glyphRun.CodepointCount] before calling.
- Ensure the CharacterHit originates from the same GlyphRun/text layout instance used for the distance query.
- Recompute character hits after any text content or layout change rather than reusing stale ones.
Example fix
// before
double d = run.GetDistanceFromCaretCharacterHit(hit);
// after
if (hit.FirstCharacterIndex < 0 || hit.FirstCharacterIndex > run.CodepointCount)
hit = new CharacterHit(Math.Max(0, Math.Min(hit.FirstCharacterIndex, run.CodepointCount)));
double d = run.GetDistanceFromCaretCharacterHit(hit); Defensive patterns
Strategy: validation
Validate before calling
bool inRange = characterHit.FirstCharacterIndex >= 0 && characterHit.FirstCharacterIndex <= glyphRun.CodepointCount; if (!inRange) characterHit = new CharacterHit(Math.Clamp(characterHit.FirstCharacterIndex, 0, glyphRun.CodepointCount));
Type guard
bool IsValidHit(GlyphRun run, CharacterHit hit) => hit.FirstCharacterIndex >= 0 && hit.FirstCharacterIndex <= run.CodepointCount;
Try / catch
try { d = run.GetDistanceFromCaretCharacterHit(hit); }
catch (ArgumentOutOfRangeException) { d = 0; hit = new CharacterHit(0); } Prevention
- Keep CharacterHit values paired with the GlyphRun instance they came from.
- Invalidate cached hits whenever the text source or layout is rebuilt.
- Clamp indices with Math.Clamp before any caret math.
When it happens
Trigger: Calling glyphRun.GetDistanceFromCaretCharacterHit(new CharacterHit(-1, ...)) or with FirstCharacterIndex > glyphRun.CodepointCount. Typically a hit produced for a different GlyphRun or text source is passed to this run.
Common situations: Hit-testing code that maps a mouse position to a character hit on one run but measures distance on another; caching CharacterHit values across text layout rebuilds where CodepointCount changed; off-by-one arithmetic computing the hit index from character offsets.
Related errors
- SR.Visual_ArgumentOutOfRange
- args
- args
- Argument out of range (position does not map to a line)
- ArgumentOutOfRangeException(authenticationType)
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/93213c1f7619cde8.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/GlyphRun.cs:482
/// <summary>
/// Given a character hit, computes the offset from the leading edge of the glyph run
/// to the leading or trailing edge of a caret stop containing the character hit.
/// If the glyph run is not hit testable, the distance of 0.0 is returned.
/// </summary>
/// <param name="characterHit">Character hit to compute the distance to.</param>
/// <returns>The offset from the leading edge of the glyph run
/// to the leading or trailing edge of a caret stop containing the character hit.</returns>
/// <exception cref="System.ArgumentOutOfRangeException">
/// The input character hit is outside of the range specified by the glyph run Unicode string.
/// </exception>
public double GetDistanceFromCaretCharacterHit(CharacterHit characterHit)
{
CheckInitialized(); // This can only be called on fully initialized GlyphRun
IList<bool> caretStops = CaretStops != null && CaretStops.Count != 0 ? CaretStops : new DefaultCaretStopList(CodepointCount);
if (characterHit.FirstCharacterIndex < 0 || characterHit.FirstCharacterIndex > CodepointCount)
throw new ArgumentOutOfRangeException(nameof(characterHit));
int caretStopIndex, codePointsUntilNextStop;
FindNearestCaretStop(
characterHit.FirstCharacterIndex,
caretStops,
out caretStopIndex,
out codePointsUntilNextStop);
// Not a hit testable glyph run.
if (caretStopIndex == -1)
return 0.0;
// Trailing edge of a caret stop that doesn't have a corresponding valid next caret stop.
if (codePointsUntilNextStop == -1 && characterHit.TrailingLength != 0)
{
return 0.0;
}
View on GitHub (pinned to 81131a70a4)