dotnet/wpf · error · ArgumentException

SR.NegativeValue (startIndex)

Error message

SR.NegativeValue (startIndex)

What it means

TextPointer.GetTextInRun validates the caller-supplied destination char[] (textBuffer) before copying run text. A negative startIndex throws ArgumentException(SR.NegativeValue, "startIndex"). This internal overload copies at most count characters into textBuffer starting at startIndex, so all slice parameters must be valid.

Solutions

  1. Clamp startIndex to Math.Max(0, startIndex) before the call.
  2. Fix the index arithmetic that produces the negative value (inspect any subtraction feeding startIndex).
  3. Prefer the simpler GetTextInRun(TextPointerContext, int) overload returning a string if you do not need the char[] destination form.

Example fix

// before
tp.GetTextInRunLogicalDirection(direction, buffer, startIndex, count);
// after
startIndex = Math.Max(0, startIndex);
tp.GetTextInRunLogicalDirection(direction, buffer, startIndex, count);
Defensive patterns

Strategy: validation

Validate before calling

if (startIndex < 0) startIndex = 0;

Try / catch

try { tp.GetTextInRunLogicalDirection(direction, buffer, startIndex, count); }
catch (ArgumentException ex) when (ex.ParamName == null && ex.Message.Contains("startIndex")) { startIndex = 0; }

Prevention

When it happens

Trigger: Calling GetTextInRun with a negative startIndex — typically a computed offset (e.g. a subtraction like position - length) that underflowed, or an uninitialized/default int passed to the buffer-copy overload.

Common situations: Manual run-walking loops where the start index arithmetic can go negative near the start of the buffer; passing -1 as a sentinel value; off-by-one loops wrapping around to negative indices.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Documents/TextPointer.cs:1752

            TextElement ancestor = this.Parent as TextElement;

            while (ancestor != null && !(ancestor is ListItem))
            {
                ancestor = ancestor.Parent as TextElement;
            }

            return ancestor as ListItem;
        }

        internal static int GetTextInRun(TextContainer textContainer, int symbolOffset, TextTreeTextNode textNode, int nodeOffset, LogicalDirection direction, char[] textBuffer, int startIndex, int count)
        {
            int skipCount;
            int finalCount;

            ArgumentNullException.ThrowIfNull(textBuffer);
            if (startIndex < 0)
            {
                throw new ArgumentException(SR.Format(SR.NegativeValue, "startIndex"));
            }
            if (startIndex > textBuffer.Length)
            {
                throw new ArgumentException(SR.Format(SR.StartIndexExceedsBufferSize, startIndex, textBuffer.Length));
            }
            if (count < 0)
            {
                throw new ArgumentException(SR.Format(SR.NegativeValue, "count"));
            }
            if (count > textBuffer.Length - startIndex)
            {
                throw new ArgumentException(SR.Format(SR.MaxLengthExceedsBufferSize, count, textBuffer.Length, startIndex));
            }
            Invariant.Assert(textNode != null, "textNode is expected to be non-null");

            textContainer.EmptyDeadPositionList();

            if (nodeOffset < 0)

View on GitHub (pinned to 81131a70a4)