{"record":{"id":"d6763be93f929c60","repo":"dotnet/wpf","slug":"argument-out-of-range-position-does-not-map-to-a-line","errorCode":null,"errorMessage":"Argument out of range (position does not map to a line)","messagePattern":"Argument out of range \\(position does not map to a line\\)","errorType":"validation","errorClass":"ArgumentOutOfRangeException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/PresentationFramework/MS/Internal/documents/TextParagraphView.cs","lineNumber":155,"sourceCode":"            // with line movement.\n            // Initialy set linesMoved to 0;\n            newSuggestedX = suggestedX;\n            linesMoved = 0;\n\n            if (count == 0)\n            {\n                return position;\n            }\n\n            ReadOnlyCollection<LineResult> lines = Lines;\n            Debug.Assert(lines != null && lines.Count > 0);\n\n            // Get index of the line that contains position.\n            int lineIndex = GetLineFromPosition(lines, position);\n            if (!(lineIndex >= 0 && lineIndex < lines.Count))\n            {\n                Debug.Assert(false);\n                throw new ArgumentOutOfRangeException(nameof(position));\n            }\n\n            // Advance line index by count.\n            int oldLineIndex = lineIndex;\n            lineIndex = Math.Max(0, lineIndex + count);\n            lineIndex = Math.Min(lines.Count - 1, lineIndex);\n            linesMoved = lineIndex - oldLineIndex;\n\n            // Get position at suggested X. \n            // If line has not been moved, return the same position. \n            // If suggested X is not provided, use the first position in the line.\n            if (linesMoved == 0)\n            {\n                positionOut = position;\n            }\n            else if (!double.IsNaN(suggestedX))\n            {\n                positionOut = lines[lineIndex].GetTextPositionFromDistance(suggestedX);","sourceCodeStart":137,"sourceCodeEnd":173,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/PresentationFramework/MS/Internal/documents/TextParagraphView.cs#L137-L173","documentation":"TextParagraphView.GetPositionAtNextLine throws this ArgumentOutOfRangeException when GetLineFromPosition cannot find a line containing the given position (lineIndex out of the line array bounds). The position belongs to another paragraph or to no laid-out line at all, so line-relative movement is impossible.","triggerScenarios":"Calling GetPositionAtNextLine with a position whose character offset does not fall within any line of this paragraph's Lines collection — e.g. a pointer from a sibling paragraph, a position beyond the paragraph's last line after a deletion, or a pointer in text that was never laid out.","commonSituations":"Hit when moving the caret vertically across paragraph boundaries using a single paragraph view, or when cached pointers become stale after text edits shift line boundaries, so the line lookup returns -1 or Count.","solutions":["Obtain the correct paragraph view for the position (owner paragraph must contain it) before calling GetPositionAtNextLine","Re-derive the position after edits instead of reusing cached pointers across document changes","Clamp/verify the position lies within the paragraph's range before the call (compare with the paragraph's start/end pointers)","Catch ArgumentOutOfRangeException and fall back to the paragraph's first/last line position to continue navigation"],"exampleFix":"// before\nvar newPos = paragraphView.GetPositionAtNextLine(stalePosition, suggestedX, lines, out sx, out len);\n// after\nif (paragraphView.Contains(stalePosition))\n{\n    var newPos = paragraphView.GetPositionAtNextLine(stalePosition, suggestedX, lines, out sx, out len);\n}\nelse\n{\n    stalePosition = paragraphView.GetTextPositionFromPoint(new Point(suggestedX, double.NaN), true) ?? stalePosition;\n}","handlingStrategy":"validation","validationCode":"if (paragraphView.Contains(position))\n{\n    var newPos = paragraphView.GetPositionAtNextLine(position, suggestedX, count, out sx, out len);\n}","typeGuard":"bool PositionBelongsToView(TextViewBase view, ITextPointer p) => view != null && view.Contains(p);","tryCatchPattern":"try { return view.GetPositionAtNextLine(position, suggestedX, count, out sx, out len); }\ncatch (ArgumentOutOfRangeException) { /* position belongs to another paragraph; hand off to the owner's view */ return null; }","preventionTips":["Route vertical navigation through the TextView that owns the position's paragraph","Discard cached positions after insert/delete operations","Clamp positions to the paragraph's range before line-relative movement","Test caret movement across paragraph boundaries"],"tags":["wpf","textblock","caret","argumentoutofrange"],"backgroundTag":"argument-out-of-range","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"}