dotnet/wpf · error · ArgumentNullException

anchorLocator.Parts

Error message

anchorLocator.Parts

What it means

GetAnnotations(ContentLocator anchorLocator) throws ArgumentNullException with the literal parameter name "anchorLocator.Parts" when the locator is non-null but its Parts collection is null. Locating annotations by anchor requires a non-null Parts list to build the XPath expression.

Solutions

  1. Initialize the Parts collection before calling: locator.Parts = new List<ContentLocatorPart>(); then add at least one ContentLocatorPart.
  2. Pass 'null' instead of a hollow locator if you intend to fetch all annotations (GetAnnotations() overload without locator).
  3. Guard the call: if (locator?.Parts == null) use the parameterless GetAnnotations().

Example fix

// before
var locator = new ContentLocator();
var results = store.GetAnnotations(locator);

// after
var locator = new ContentLocator();
locator.Parts.Add(new ContentLocatorPart(new XmlQualifiedName("Page", "...")));
var results = store.GetAnnotations(locator);
Defensive patterns

Strategy: type-guard

Validate before calling

if (locator == null || locator.Parts == null) { /* use parameterless GetAnnotations() or initialize Parts */ }

Type guard

bool HasParts(ContentLocator locator) => locator?.Parts != null && locator.Parts.Count > 0;

Try / catch

try { return store.GetAnnotations(locator); }
catch (ArgumentNullException) { return store.GetAnnotations(); }

Prevention

When it happens

Trigger: Calling XmlStreamStore.GetAnnotations(locator) where locator is a valid ContentLocator instance but locator.Parts was never initialized (null).

Common situations: Deserializing a ContentLocator where the Parts element was absent; constructing 'new ContentLocator()' without calling Parts.Add or assigning a parts collection; passing a default/uninitialized locator.

Related errors


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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Annotations/Storage/XmlStreamStore.cs:232

        ///     that contains a locator that begins with the locator parts
        ///     in anchorLocator.
        /// </summary>
        /// <param name="anchorLocator">the locator we are looking for</param>
        /// <returns>
        ///    A list of annotations that have locators in their anchors
        ///    starting with the same locator parts list as of the input locator
        ///    If no such annotations an empty list will be returned. The method
        ///    never returns null.
        /// </returns>
        /// <exception cref="ObjectDisposedException">if object has been Disposed</exception>
        /// <exception cref="InvalidOperationException">the stream is null</exception>
        public override IList<Annotation> GetAnnotations(ContentLocator anchorLocator)
        {
            // First we generate the XPath expression
            ArgumentNullException.ThrowIfNull(anchorLocator);

            if (anchorLocator.Parts == null)
                throw new ArgumentNullException("anchorLocator.Parts");

            //fire trace event
            EventTrace.EasyTraceEvent(EventTrace.Keyword.KeywordAnnotation, EventTrace.Event.GetAnnotationByLocBegin);
            IList<Annotation> annotations = null;
            try
            {
                string query = $@"//{AnnotationXmlConstants.Prefixes.CoreSchemaPrefix}:{AnnotationXmlConstants.Elements.ContentLocator}";

                if (anchorLocator.Parts.Count > 0)
                {
                    query += @"/child::*[1]/self::";
                    for (int i = 0; i < anchorLocator.Parts.Count; i++)
                    {
                        if (anchorLocator.Parts[i] != null)
                        {
                            if (i > 0)
                            {
                                query += @"/following-sibling::";

View on GitHub (pinned to 81131a70a4)