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

  1. Check TextSchema.IsValidChildOfContainer(containerType, typeof(Paragraph)) before inserting; fall back to a LineBreak instead.
  2. Use a container that supports paragraphs (FlowDocument with RichTextBox/FlowDocumentScrollViewer) for paragraph insertion.
  3. 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

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


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)