{"record":{"id":"6c63df84eec94a72","repo":"dotnet/wpf","slug":"sr-format-sr-invalidlocatorpart-textselectionprocessor","errorCode":null,"errorMessage":"SR.Format(SR.InvalidLocatorPart, TextSelectionProcessor.CountAttribute)","messagePattern":"SR\\.Format\\(SR\\.InvalidLocatorPart, TextSelectionProcessor\\.CountAttribute\\)","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/PresentationFramework/MS/Internal/Annotations/Anchoring/TextSelectionProcessor.cs","lineNumber":201,"sourceCode":"        /// <exception cref=\"ArgumentNullException\">locatorPart or startNode are\n        /// null</exception>\n        /// <exception cref=\"ArgumentException\">locatorPart is of the incorrect type</exception>\n        public override Object ResolveLocatorPart(ContentLocatorPart locatorPart, DependencyObject startNode, out AttachmentLevel attachmentLevel)\n        {\n            ArgumentNullException.ThrowIfNull(startNode);\n            ArgumentNullException.ThrowIfNull(locatorPart);\n\n            if (CharacterRangeElementName != locatorPart.PartType)\n                throw new ArgumentException(SR.Format(SR.IncorrectLocatorPartType, $\"{locatorPart.PartType.Namespace}:{locatorPart.PartType.Name}\"), nameof(locatorPart));\n\n            // First we extract the offset and length of the\n            // text range from the locator part.\n            int startOffset = 0;\n            int endOffset = 0;\n\n            string stringCount = locatorPart.NameValuePairs[CountAttribute];\n            if (stringCount == null)\n                throw new ArgumentException(SR.Format(SR.InvalidLocatorPart, TextSelectionProcessor.CountAttribute));\n            int count = Int32.Parse(stringCount, NumberFormatInfo.InvariantInfo);\n\n            TextAnchor anchor = new TextAnchor();\n\n            attachmentLevel = AttachmentLevel.Unresolved;\n\n            for (int i = 0; i < count; i++)\n            {\n                GetLocatorPartSegmentValues(locatorPart, i, out startOffset, out endOffset);\n\n                // Now we grab the TextRange so we can create a selection.\n                // TextBox doesn't expose its internal TextRange so we use\n                // its API for creating and getting the selection.\n                ITextPointer elementStart;\n                ITextPointer elementEnd;\n                // If we can't get the start/end of the node then we can't resolve the locator part\n                if (!GetNodesStartAndEnd(startNode, out elementStart, out elementEnd))\n                    return null;","sourceCodeStart":183,"sourceCodeEnd":219,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/PresentationFramework/MS/Internal/Annotations/Anchoring/TextSelectionProcessor.cs#L183-L219","documentation":"ResolveLocatorPart reads the 'Count' attribute from the locator part's name/value pairs to determine the character-range length. If the attribute is missing the locator part is malformed and cannot be resolved, so this ArgumentException is thrown naming the missing attribute.","triggerScenarios":"Passing a CharacterRange-typed ContentLocatorPart that lacks the CountAttribute ('Count') name/value pair — e.g. constructed by hand with only Start set, deserialized with missing attributes, or corrupted/partial annotation data.","commonSituations":"Hand-rolling ContentLocatorPart entries instead of using GenerateLocatorParts; annotation streams from older/other versions with a different schema; manual XML editing of annotation stores.","solutions":["Build the locator part via TextSelectionProcessor.GenerateLocatorParts so both Start and Count attributes are populated.","Validate locatorPart.NameValuePairs contains CountAttribute before calling ResolveLocatorPart.","Recreate the locator from the original selection if the stored part is malformed.","Catch ArgumentException and treat the locator as unresolvable (AttachmentLevel.Unresolved)."],"exampleFix":"// before\nvar part = new ContentLocatorPart(TextSelectionProcessor.CharacterRangeElementName);\npart.NameValuePairs[TextSelectionProcessor.SegmentAttribute] = \"10\";\nvar anchor = processor.ResolveLocatorPart(part, startNode, out level);\n// after\nvar part = new ContentLocatorPart(TextSelectionProcessor.CharacterRangeElementName);\npart.NameValuePairs[TextSelectionProcessor.SegmentAttribute] = \"10\";\npart.NameValuePairs[TextSelectionProcessor.CountAttribute] = \"25\";\nvar anchor = processor.ResolveLocatorPart(part, startNode, out level);","handlingStrategy":"validation","validationCode":"if (locatorPart.NameValuePairs[TextSelectionProcessor.CountAttribute] == null)\n    throw new InvalidOperationException(\"LocatorPart missing Count attribute\");","typeGuard":"static bool HasCountAttribute(ContentLocatorPart p) => p.NameValuePairs[TextSelectionProcessor.CountAttribute] != null;","tryCatchPattern":"try { result = processor.ResolveLocatorPart(locatorPart, startNode, out level); }\ncatch (ArgumentException ex) when (ex.Message.Contains(TextSelectionProcessor.CountAttribute)) { level = AttachmentLevel.Unresolved; result = null; }","preventionTips":["Always build CharacterRange locator parts via GenerateLocatorParts (never by hand).","Validate Start and Count attributes exist on stored locator parts before resolving.","Sanity-check annotation stores after schema/version upgrades."],"tags":["wpf","annotations","argumentexception","malformed-locatorpart","missing-attribute"],"backgroundTag":"invalid-argument-format","analyzedSha":"81131a70a4c573cd62748a5c36908fc4d662daa9","analyzedAt":"2026-09-14T10:12:48.479Z","contentChangedAt":"2026-09-14T10:12:48.479Z","schemaVersion":2},"datasetVersion":"2026-09-21T21:30:21.729Z"}