dotnet/wpf · error · InvalidOperationException
SR.TextSchema_IllegalElement (Paragraph, containerType)
Error message
SR.TextSchema_IllegalElement (Paragraph, containerType)
What it means
TextPointer.InsertParagraphBreak validates the schema: if the TextContainer has a parent (e.g. a TextBlock or FlowDocument), TextSchema.IsValidChildOfContainer must allow a Paragraph there. When the container type cannot legally contain a Paragraph (for example a Paragraph inside a TextBlock), it throws InvalidOperationException with SR.TextSchema_IllegalElement formatted with ("Paragraph", containerType).
Solutions
- Check TextSchema.IsValidChildOfContainer(containerType, typeof(Paragraph)) before inserting; fall back to a LineBreak instead.
- Use a container that supports paragraphs (FlowDocument with RichTextBox/FlowDocumentScrollViewer) for paragraph insertion.
- In a TextBlock, insert a Run with a newline semantics or a LineBreak inline instead of splitting into Paragraphs.
Example fix
// before
pointer.InsertParagraphBreak();
// after
var containerType = pointer.TextContainer.Parent?.GetType();
if (containerType == null || TextSchema.IsValidChildOfContainer(containerType, typeof(Paragraph)))
pointer.InsertParagraphBreak();
else
pointer.InsertLineBreak(); Defensive patterns
Strategy: validation
Validate before calling
var containerType = pointer.TextContainer.Parent?.GetType(); bool canInsertParagraph = containerType == null || TextSchema.IsValidChildOfContainer(containerType, typeof(Paragraph)); if (!canInsertParagraph) pointer.InsertLineBreak();
Try / catch
try { pointer.InsertParagraphBreak(); }
catch (InvalidOperationException) { pointer.InsertLineBreak(); } Prevention
- Use paragraph-capable containers (FlowDocument/RichTextBox) for paragraph insertion
- Check TextSchema.IsValidChildOfContainer before structural edits
- In TextBlock, use LineBreak instead of Paragraph
When it happens
Trigger: Calling InsertParagraphBreak on a TextPointer whose container is a type that forbids Paragraph children — e.g. pressing Enter / inserting a paragraph break inside a TextBlock, or inside containers like Span-derived hosting types that only accept Inlines.
Common situations: Rich-text editing surfaces built on TextBlock instead of RichTextBox/FlowDocument where users press Enter; programmatic insertion of Paragraph objects into inline-only containers; automation or IME code that inserts paragraph breaks regardless of container type.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- SR.Format(SR.InDifferentParagraphs, "start", "end")
- SR.Format(SR.TextSchema_TextIsNotAllowedInThisContext…
- SR.TextSchema_CannotSplitElement (ancestor type name)
- SR.TextSchema_ChildTypeIsInvalid
- " }} " element found. Expected fixed page element ( }} ).
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/0da9b3fcde214248.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Documents/TextPointer.cs:1422
/// (for special insertion positions such as table row end, BlockUIContainer boundaries, etc),
/// this method creates a paragraph by using rules of EnsureInsertionPosition()
/// and returns a normalized position at the start of the paragraph created.
/// </returns>
/// <exception cref="InvalidOperationException">
/// Throws InvalidOperationException when this position has a non-splittable ancestor such as Hyperlink,
/// since we cannot successfully split upto the parent paragraph in this case.
/// </exception>
public TextPointer InsertParagraphBreak()
{
_tree.EmptyDeadPositionList();
SyncToTreeGeneration();
if (this.TextContainer.Parent != null)
{
Type containerType = this.TextContainer.Parent.GetType();
if (!TextSchema.IsValidChildOfContainer(containerType, typeof(Paragraph)))
{
throw new InvalidOperationException(SR.Format(SR.TextSchema_IllegalElement, "Paragraph", containerType));
}
}
Inline ancestor = this.GetNonMergeableInlineAncestor();
if (ancestor != null)
{
// Cannot split a hyperlink element!
throw new InvalidOperationException(SR.Format(SR.TextSchema_CannotSplitElement, ancestor.GetType().Name));
}
TextPointer position;
_tree.BeginChange();
try
{
position = TextRangeEdit.InsertParagraphBreak(this, /*moveIntoSecondParagraph:*/true);
}View on GitHub (pinned to 81131a70a4)