dotnet/wpf · error · InvalidOperationException
SR.Format(SR.TextSchema_CannotSplitElement…
Error message
SR.Format(SR.TextSchema_CannotSplitElement, nonMergeableAncestor.GetType().Name)
What it means
The Span(TextPointer start, TextPointer end) constructor throws InvalidOperationException with SR.TextSchema_CannotSplitElement (containing the element type name, e.g. 'Hyperlink') when either endpoint sits inside a non-mergeable inline element such as a Hyperlink. Creating the Span would require splitting that element, which the text schema forbids, so the constructor refuses regardless of argument order.
Solutions
- Move the start/end position outside the Hyperlink (e.g. to its ElementStart/ElementEnd) before constructing the Span.
- Check GetNonMergeableInlineAncestor() on both endpoints first and reject or adjust positions when non-null.
- Split the operation into ranges that exclude the hyperlink, or operate on the Hyperlink element itself instead of positions inside it.
- Catch InvalidOperationException and report that the position inside an un-splittable element (name in message) is not allowed.
Example fix
// before
var span = new Span(insideHyperlinkPointer, end);
// after
if (insideHyperlinkPointer.GetNonMergeableInlineAncestor() != null)
insideHyperlinkPointer = insideHyperlinkPointer.GetNonMergeableInlineAncestor().ElementEnd;
var span = new Span(insideHyperlinkPointer, end); Defensive patterns
Strategy: validation
Validate before calling
if (start.GetNonMergeableInlineAncestor() != null || end.GetNonMergeableInlineAncestor() != null)
throw new InvalidOperationException("Range endpoints lie inside a non-mergeable inline element (e.g. Hyperlink)."); Type guard
static bool OutsideNonMergeableInline(TextPointer p) => p.GetNonMergeableInlineAncestor() == null;
Try / catch
try { span = new Span(start, end); }
catch (InvalidOperationException ex) when (ex.Message.Contains("split")) { /* move endpoints outside the element and retry */ } Prevention
- Snap range endpoints out of Hyperlinks via GetNonMergeableInlineAncestor()/ElementEnd
- Disable editing operations inside hyperlinks in UI where Spans are built
- Unit-test range creation against documents containing hyperlinks and embedded UIElements
When it happens
Trigger: new Span(start, end) where start.GetNonMergeableInlineAncestor() (or the same for end) returns non-null - typically a position inside a Hyperlink (or other non-mergeable Inline) in a FlowDocument.
Common situations: Programmatically inserting/formatting content within a hyperlink in a RichTextBox/FlowDocument; building a Span whose endpoint lands inside UIElement-anchored or embedded inline content; text processing scripts that walk into hyperlinked text runs.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- SR.NoElementObject
- SR.RowCacheCannotModifyNonExistentLayout
- SR.TextPositionIsFrozen
- Animation_Invalid_DefaultValue
- args
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/300c0ea0207f4aa5.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Documents/Span.cs:116
start.TextContainer.BeginChange();
try
{
start = TextRangeEditTables.EnsureInsertionPosition(start);
Invariant.Assert(start.Parent is Run);
end = TextRangeEditTables.EnsureInsertionPosition(end);
Invariant.Assert(end.Parent is Run);
if (start.Paragraph != end.Paragraph)
{
throw new ArgumentException(SR.Format(SR.InDifferentParagraphs, "start", "end"));
}
// If start or end positions have a Hyperlink ancestor, we cannot split them.
Inline nonMergeableAncestor;
if ((nonMergeableAncestor = start.GetNonMergeableInlineAncestor()) != null)
{
throw new InvalidOperationException(SR.Format(SR.TextSchema_CannotSplitElement, nonMergeableAncestor.GetType().Name));
}
if ((nonMergeableAncestor = end.GetNonMergeableInlineAncestor()) != null)
{
throw new InvalidOperationException(SR.Format(SR.TextSchema_CannotSplitElement, nonMergeableAncestor.GetType().Name));
}
TextElement commonAncestor = TextElement.GetCommonAncestor((TextElement)start.Parent, (TextElement)end.Parent);
while (start.Parent != commonAncestor)
{
start = SplitElement(start);
}
while (end.Parent != commonAncestor)
{
end = SplitElement(end);
}
if (start.Parent is Run)View on GitHub (pinned to 81131a70a4)