dotnet/wpf · error · ArgumentException

System.ArgumentException

Error message

System.ArgumentException

What it means

WordBreaker.MoveByDistance throws System.ArgumentException when the requested move would push the breaker's position outside the text container: newPosition < 0 or > _container.Text.Length. The class comment states this explicitly — it is an out-of-bounds move guard for the text-breaking iterator.

Solutions

  1. Clamp distance so _position + distance stays within [0, Text.Length] before calling
  2. Check for end-of-text before requesting further moves (compare position to Text.Length)
  3. Catch ArgumentException as the signal that iteration is past the end and stop breaking
  4. Recreate the WordBreaker against the current text if the text changed mid-iteration

Example fix

// before
breaker.MoveByDistance(remainingWidthChars); // may run past end
// after
int dist = Math.Min(remainingWidthChars, breaker.PositionRemaining);
if (dist > 0) breaker.MoveByDistance(dist);
Defensive patterns

Strategy: validation

Validate before calling

int dist = Math.Clamp(distance, -position, containerText.Length - position);

Type guard

bool CanMoveBy(int position, int distance, int textLength) => position + distance >= 0 && position + distance <= textLength;

Try / catch

try { breaker.MoveByDistance(distance); }
catch (ArgumentException) { /* iteration past end: stop breaking */ break; }

Prevention

When it happens

Trigger: Calling MoveByDistance(distance) where _position + distance is negative or beyond Text.Length. Internally reachable via MoveNaviForward/MoveNaviBackward/GenerateText/GeneratePosition/BreakText when callers pass distances computed from mismatched text lengths (e.g. text changed between calls).

Common situations: Line-breaking/word-wrapping code that advances by characters after the text was edited; callers passing a byte vs char count mismatch; wrapped text measuring code that moves by more than the remaining length.

Related errors


AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14). Data as JSON: /api/errors/d5b4910fbfbb411a. Report an issue: GitHub.

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/UIAutomation/UIAutomationClientSideProviders/MS/Internal/AutomationProxies/WordBreaker.cs:219

        public void Move(LogicalDirection direction)
        {
            // this should never get called.
            throw new NotImplementedException();
        }

        public void MoveToPosition(TextPosition position)
        {
            _position = position.Position;
        }

        public void MoveByDistance(int distance)
        {
            // throw ArgumentException if position would be moved out of bounds.
            int newPosition = _position + distance;
            if (newPosition < 0 || newPosition > _container.Text.Length)
            {
                throw new System.ArgumentException();
            }

            _position = newPosition;
        }
    }

    // the following additional Avalon Text types are required so the WordBreaker class will compile as-is.
    internal delegate void TextContainerChangedEventHandler(object target, TextContainerChangedEventArgs args);
    internal class TextContainerChangedEventArgs 
    {
        // To appease the FxCop
        private TextContainerChangedEventArgs()
        { }
    }
    internal class InlineElement
    {
        // To appease the FxCop
        private InlineElement()

View on GitHub (pinned to 81131a70a4)