dotnet/wpf · error · ArgumentException

SR.InvalidLocatorPart

Error message

SR.InvalidLocatorPart (SegmentAttribute{n})

What it means

After confirming the part type, GetLocatorPartSegmentValues reads NameValuePairs['Segment{n}'] for the requested segment number. A missing (null) value means the locator part is malformed, so it throws ArgumentException(SR.InvalidLocatorPart, Segment{n}).

Solutions

  1. Ensure NameValuePairs contains Segment{i} for every i in [0, Count).
  2. Let GenerateLocatorParts create segments instead of manual construction.
  3. When editing stored annotations, preserve every Segment attribute.

Example fix

// before
part.NameValuePairs["Count"] = "2";
part.NameValuePairs["Segment0"] = "..."; // Segment1 missing
// after
part.NameValuePairs["Count"] = "2";
part.NameValuePairs["Segment0"] = "...";
part.NameValuePairs["Segment1"] = "...";
Defensive patterns

Strategy: validation

Validate before calling

int count = int.Parse(part.NameValuePairs["Count"], CultureInfo.InvariantCulture);
for (int i = 0; i < count; i++) if (!part.NameValuePairs.ContainsKey("Segment" + i)) throw new InvalidOperationException($"Missing Segment{i}");

Try / catch

try { processor.ResolveLocatorPart(part, node, out var level); } catch (ArgumentException ex) { /* malformed locator part — skip or rebuild */ }

Prevention

When it happens

Trigger: ResolveLocatorPart invoked with a FixedText locator part lacking the 'Segment0'/'Segment1'... attribute for a given segment index, e.g. Count says 2 segments but only Segment0 exists.

Common situations: Corrupt or hand-edited annotation XML; programmatic construction that sets Count higher than the number of Segment attributes stored; attribute naming typos (lowercase 'segment').

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/MS/Internal/Annotations/Anchoring/FixedTextSelectionProcessor.cs:497

        }

        /// <summary>
        ///     Extracts the values of attributes from a locator part.
        /// </summary>
        /// <param name="locatorPart">the locator part to extract values from</param>
        /// <param name="segmentNumber">number of segment value to retrieve</param>
        /// <param name="start">the start point value based on StartXAttribute and StartYAttribute values</param>
        /// <param name="end">the end point value based on EndXAttribyte and EndYattribute values</param>
        private void GetLocatorPartSegmentValues(ContentLocatorPart locatorPart, int segmentNumber, out Point start, out Point end)
        {
            ArgumentNullException.ThrowIfNull(locatorPart);

            if (FixedTextElementName != locatorPart.PartType)
                throw new ArgumentException(SR.Format(SR.IncorrectLocatorPartType, $"{locatorPart.PartType.Namespace}:{locatorPart.PartType.Name}"), nameof(locatorPart));

            string segmentValue = locatorPart.NameValuePairs[TextSelectionProcessor.SegmentAttribute + segmentNumber.ToString(NumberFormatInfo.InvariantInfo)];
            if (segmentValue == null)
                throw new ArgumentException(SR.Format(SR.InvalidLocatorPart, TextSelectionProcessor.SegmentAttribute + segmentNumber.ToString(NumberFormatInfo.InvariantInfo)));

            ReadOnlySpan<char> segmentValueSpan = segmentValue.AsSpan();
            Span<Range> splitRegions = stackalloc Range[5];

            if (segmentValueSpan.Split(splitRegions, TextSelectionProcessor.Separator) != 4)
                throw new ArgumentException(SR.Format(SR.InvalidLocatorPart, TextSelectionProcessor.SegmentAttribute + segmentNumber.ToString(NumberFormatInfo.InvariantInfo)));

            start = GetPoint(segmentValueSpan[splitRegions[0]], segmentValueSpan[splitRegions[1]]);
            end = GetPoint(segmentValueSpan[splitRegions[2]], segmentValueSpan[splitRegions[3]]);
        }

        /// <summary>
        /// Calculates <see cref="Point"/> out of X and Y values supplied as a <see cref="string"/>.
        /// </summary>
        /// <param name="xValue">x string value</param>
        /// <param name="yValue">y string value</param>
        /// <returns>Initialized <see cref="Point"/> structure.</returns>
        private static Point GetPoint(ReadOnlySpan<char> xValue, ReadOnlySpan<char> yValue)

View on GitHub (pinned to 81131a70a4)