{"record":{"id":"62f4551c201de9eb","repo":"dotnet/wpf","slug":"sr-textschema-illegalhyperlinkchild-nextelement-gettype","errorCode":null,"errorMessage":"SR.TextSchema_IllegalHyperlinkChild (nextElement.GetType())","messagePattern":"SR\\.TextSchema_IllegalHyperlinkChild \\(nextElement\\.GetType\\(\\)\\)","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Documents/TextSchema.cs","lineNumber":897,"sourceCode":"        // It this context, the element or one of its ancestors is a Hyperlink.\n        private static bool HasIllegalHyperlinkDescendant(TextElement element, bool throwIfIllegalDescendent)\n        {\n            TextPointer start = element.ElementStart;\n            TextPointer end = element.ElementEnd;\n\n            while (start.CompareTo(end) < 0)\n            {\n                TextPointerContext forwardContext = start.GetPointerContext(LogicalDirection.Forward);\n                if (forwardContext == TextPointerContext.ElementStart)\n                {\n                    TextElement nextElement = (TextElement)start.GetAdjacentElement(LogicalDirection.Forward);\n\n                    if (nextElement is Hyperlink ||\n                        nextElement is AnchoredBlock)\n                    {\n                        if (throwIfIllegalDescendent)\n                        {\n                            throw new InvalidOperationException(SR.Format(SR.TextSchema_IllegalHyperlinkChild, nextElement.GetType()));\n                        }\n                        return true;\n                    }\n                }\n\n                start = start.GetNextContextPosition(LogicalDirection.Forward);\n            }\n            return false;\n        }\n\n        private static bool AreBrushesEqual(Brush brush1, Brush brush2)\n        {\n            SolidColorBrush solidBrush1 = brush1 as SolidColorBrush;\n            if (solidBrush1 != null)\n            {\n                return solidBrush1.Color.Equals(((SolidColorBrush)brush2).Color);\n            }\n            else","sourceCodeStart":879,"sourceCodeEnd":915,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Documents/TextSchema.cs#L879-L915","documentation":"HasIllegalHyperlinkDescendant scans a position range for Hyperlink or AnchoredBlock elements that would illegally descend from a hyperlink. If one is found and throwIfIllegalDescendent is true, an InvalidOperationException is thrown naming the offending element's type. It enforces the rule that Hyperlink content cannot contain nested Hyperlinks or block-level AnchoredBlocks.","triggerScenarios":"Text edits (e.g. applying Hyperlink formatting over a selection, TextRange save/paste, splitting operations) that would leave a Hyperlink or AnchoredBlock (Paragraph/Table/List/Floater/Figure/Section) inside an existing Hyperlink's scope; detected via GetNextContextPosition scan from the range start.","commonSituations":"Applying link formatting to a selection that already contains a link; paste operations merging content inside a hyperlink; code that splits a Span at a Hyperlink boundary producing nested links.","solutions":["Before applying a Hyperlink over a range, remove/flatten existing nested Hyperlink elements within the selection","Split the enclosing Hyperlink so the edited range lies outside any existing link scope (TextRangeEdit helpers do this; replicate it for custom code)","Replace illegal AnchoredBlock descendants with inline equivalents (Run/Span) inside link content","Catch InvalidOperationException, locate the nested element via the message type, and restructure the tree before retrying the edit"],"exampleFix":"// before\nTextRange selection = new TextRange(start, end); // selection contains an existing Hyperlink\nselection.ApplyPropertyValue(TextElement.ForegroundProperty, Brushes.Blue); // edit crossing Hyperlink boundary -> HasIllegalHyperlinkDescendant throws when creating nested link\n// after\nforeach (var hl in FindHyperlinks(selection)) FlattenHyperlink(hl); // unwrap nested links first\nselection.ApplyPropertyValue(...);","handlingStrategy":"validation","validationCode":"static bool RangeHasIllegalLinkDescendant(TextPointer start, TextPointer end) => /* scan with GetNextContextPosition; throw-free probe via throwIfIllegalDescendent:false */ HasIllegalHyperlinkDescendant(start, end, false);","typeGuard":"static bool IsSafeLinkContent(TextElement e) => !(e is Hyperlink) && !(e is AnchoredBlock);","tryCatchPattern":"try { ApplyLinkFormatting(range); } catch (InvalidOperationException ex) when (ex.Message.Contains(\"IllegalHyperlinkChild\")) { SplitEnclosingHyperlinks(range); ApplyLinkFormatting(range); }","preventionTips":["Unwrap existing Hyperlinks in a selection before applying link formatting","Split Spans/Hyperlinks at range boundaries before edits","Run probe scans with throw flags off in edit pipelines"],"tags":["wpf","hyperlink","text-editing"],"backgroundTag":"schema-validation-failed","analyzedSha":"81131a70a4c573cd62748a5c36908fc4d662daa9","analyzedAt":"2026-09-14T10:12:48.479Z","contentChangedAt":"2026-09-14T10:12:48.479Z","schemaVersion":2},"datasetVersion":"2026-09-22T01:17:13.364Z"}