dotnet/wpf · error · InvalidOperationException

SR.TextSchema_CannotInsertContentInThisPosition

Error message

SR.TextSchema_CannotInsertContentInThisPosition

What it means

This public TextPointer insertion API (e.g. FixSchemaAndInsertText / insertion via TextRangeEdit) validates that the content to insert is schema-valid at the position. If the content contains no valid child for the position AND position.Parent is null, the schema cannot be fixed up (there is no element to add children to), so it throws InvalidOperationException(SR.TextSchema_CannotInsertContentInThisPosition).

Solutions

  1. Ensure the document has at least one Paragraph before inserting (e.g. richTextBox.Document.Blocks.Add(new Paragraph())).
  2. Wrap content in schema-appropriate elements (Paragraph for text at block positions, Run for text inside paragraphs) before insertion.
  3. Use higher-level APIs like TextRange.Text or RichTextBox.CaretPosition.InsertTextInRun rather than raw insertion at root positions.

Example fix

// before
richTextBox.Document.ContentStart.InsertTextInRun("hello");
// after
if (richTextBox.Document.Blocks.Count == 0)
    richTextBox.Document.Blocks.Add(new Paragraph());
var p = richTextBox.Document.Blocks.FirstBlock as Paragraph;
p.ContentStart.InsertTextInRun("hello");
Defensive patterns

Strategy: validation

Validate before calling

if (richTextBox.Document.Blocks.Count == 0)
    richTextBox.Document.Blocks.Add(new Paragraph(new Run("")));

Type guard

static bool CanInsertContent(TextPointer p) => p.Parent != null;

Try / catch

try { pointer.InsertTextInRun(text); }
catch (InvalidOperationException) { EnsureParagraph(); repositionedPointer.InsertTextInRun(text); }

Prevention

When it happens

Trigger: Inserting text/elements at a TextPointer whose Parent is null — e.g. at the bare root of an empty document with content that is not allowed there (like inserting a Run directly at the document root where a Paragraph wrapper is required but cannot be inferred).

Common situations: Inserting plain text at Document.ContentStart of an empty RichTextBox through low-level APIs without a paragraph; inserting schema-incompatible content (tables inside inline content) at root-level positions.

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/71fea201d27db782. Report an issue: GitHub.

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Documents/TextPointer.cs:3548

            return symbolType;
        }

        // Inserts an Inline at the current location, adding contextual
        // elements as needed to enforce the schema.
        internal void InsertInline(Inline inline)
        {
            TextPointer position = this;

            // Check for hyperlink schema validity first -- we'll throw on an illegal Hyperlink descendent insert.
            bool isValidChild = TextSchema.ValidateChild(position, /*childType*/inline.GetType(), false /* throwIfIllegalChild */, true /* throwIfIllegalHyperlinkDescendent */);

            // Now, it is safe to assume that !isValidChild will be the case of incomplete content.
            if (!isValidChild)
            {
                if (position.Parent == null)
                {
                    // We should try to fix up the schema by adding elements instead of throwing here.
                    throw new InvalidOperationException(SR.TextSchema_CannotInsertContentInThisPosition);
                }

                // Ensure text content.
                position = TextRangeEditTables.EnsureInsertionPosition(this);
                Invariant.Assert(position.Parent is Run, "EnsureInsertionPosition() must return a position in text content");
                Run run = (Run)position.Parent;

                if (run.IsEmpty)
                {
                    // Remove the implicit (empty) Run, since we are going to insert an inline at this position.
                    run.RepositionWithContent(null);
                }
                else
                {
                    // Position is parented by Run, split formatting elements to prepare for inserting inline at this position.
                    position = TextRangeEdit.SplitFormattingElement(position, /*keepEmptyFormatting:*/false);
                }

View on GitHub (pinned to 81131a70a4)