dotnet/wpf · error · ArgumentException

SR.IncorrectLocatorPartType

Error message

SR.IncorrectLocatorPartType ({locatorPart.PartType.Namespace}:{locatorPart.PartType.Name})

What it means

DataIdProcessor.ResolveLocatorPart only accepts locator parts whose PartType equals the processor's DataIdElementName. If the supplied ContentLocatorPart has any other PartType, it throws ArgumentException with SR.IncorrectLocatorPartType describing the offending type's namespace:name, naming the 'locatorPart' parameter. Each anchor processor handles exactly one locator-part type, so mismatched parts must be routed elsewhere.

Solutions

  1. Ensure the ContentLocatorPart is constructed with the exact PartType expected by DataIdProcessor (DataIdElementName) before calling ResolveLocatorPart.
  2. Look up the correct processor via AnnotationResource/locator part type matching instead of calling a fixed processor directly.
  3. If migrating old annotations, regenerate the locator part with the current DataId element type.
  4. Check locatorPart.PartType against the expected type first and skip/route to the appropriate processor when different.

Example fix

// before
processor.ResolveLocatorPart(wrongLocatorPart, node, out continueResolving);
// after
if (DataIdProcessor.DataIdElementName == wrongLocatorPart.PartType)
    processor.ResolveLocatorPart(wrongLocatorPart, node, out continueResolving);
else
    matchingProcessor.ResolveLocatorPart(wrongLocatorPart, node, out continueResolving);
Defensive patterns

Strategy: type-guard

Validate before calling

if (locatorPart == null || !DataIdProcessor.DataIdElementName.Equals(locatorPart.PartType))
    throw new InvalidOperationException("Locator part is not a DataId part; route to correct processor.");

Type guard

static bool IsDataIdPart(ContentLocatorPart part) =>
    part != null && part.PartType == DataIdProcessor.DataIdElementName;

Try / catch

try { processor.ResolveLocatorPart(locatorPart, node, out var cont); }
catch (ArgumentException ex) when (ex.ParamName == "locatorPart") { RouteToMatchingProcessor(locatorPart, node); }

Prevention

When it happens

Trigger: Passing a ContentLocatorPart whose PartType is not DataIdProcessor's expected DataIdElementName into ResolveLocatorPart — e.g. feeding a PathProcessor/CharacterRangePart-type locator part to the DataId processor, or constructing a ContentLocatorPart with the wrong XName/type.

Common situations: Building annotation locators programmatically and mismatching processor types; deserializing annotation XML from another schema/version whose locator part type differs; iterating an anchor's locator parts in order and handing each to the wrong processor.

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/9dfeccb00395283e. Report an issue: GitHub.

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/MS/Internal/Annotations/Anchoring/DataIdProcessor.cs:181

        /// </summary>
        /// <param name="locatorPart">locator part to be matched, must be of the type
        /// handled by this processor</param>
        /// <param name="startNode">logical tree node to start search at</param>
        /// <param name="continueResolving">return flag indicating whether the search
        /// should continue (presumably because the search was not exhaustive)</param>
        /// <returns>returns a node that matches the locator part; null if no such
        /// node is found</returns>
        /// <exception cref="ArgumentNullException">locatorPart or startNode are
        /// null</exception>
        /// <exception cref="ArgumentException">locatorPart is of the incorrect
        /// type</exception>
        public override DependencyObject ResolveLocatorPart(ContentLocatorPart locatorPart, DependencyObject startNode, out bool continueResolving)
        {
            ArgumentNullException.ThrowIfNull(locatorPart);
            ArgumentNullException.ThrowIfNull(startNode);

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

            // Initial value
            continueResolving = true;

            // Get the values from the locator part...
            string id = locatorPart.NameValuePairs[ValueAttributeName];
            if (id == null)
            {
                throw new ArgumentException(SR.Format(SR.IncorrectLocatorPartType, $"{locatorPart.PartType.Namespace}:{locatorPart.PartType.Name}"), nameof(locatorPart));
            }

            // and from the node to examine.
            string nodeId = GetNodeId(startNode);

            if (nodeId != null)
            {
                if (nodeId.Equals(id))
                {

View on GitHub (pinned to 81131a70a4)