{"record":{"id":"ad54899e060a7b2c","repo":"dotnet/wpf","slug":"sr-format-sr-textschema-textisnotallowedinthiscontext","errorCode":null,"errorMessage":"SR.Format(SR.TextSchema_TextIsNotAllowedInThisContext, Element.GetType().Name)","messagePattern":"SR\\.Format\\(SR\\.TextSchema_TextIsNotAllowedInThisContext, Element\\.GetType\\(\\)\\.Name\\)","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/PresentationFramework/MS/Internal/PtsHost/ContainerParagraph.cs","lineNumber":1001,"sourceCode":"        //     * if block, UIElementParagraph\n        //     * if inline, TextParagraph\n        // (5) if textPointer points to TextContainer.End, NULL\n        // ------------------------------------------------------------------\n        protected virtual BaseParagraph GetParagraph(ITextPointer textPointer, bool fEmptyOk)\n        {\n            BaseParagraph paragraph = null;\n\n            switch (textPointer.GetPointerContext(LogicalDirection.Forward))\n            {\n                case TextPointerContext.Text:\n                    // Text paragraph\n\n                    // WORKAROUND FOR SCHEMA VALIDATION\n                    if(textPointer.TextContainer.Start.CompareTo(textPointer) > 0)\n                    {\n                        if(!(Element is TextElement) || ((TextElement)Element).ContentStart != textPointer)\n                        {\n                            throw new InvalidOperationException(SR.Format(SR.TextSchema_TextIsNotAllowedInThisContext, Element.GetType().Name));\n                        }\n                    }\n\n                    paragraph = new TextParagraph(Element, StructuralCache);\n                    break;\n\n                case TextPointerContext.ElementEnd:\n                    // The end of TextElement\n                    Invariant.Assert(textPointer is TextPointer);\n                    Invariant.Assert(Element == ((TextPointer)textPointer).Parent);\n\n                    if(!fEmptyOk)\n                    {\n                        paragraph = new TextParagraph(Element, StructuralCache);\n                    }\n                    break;\n\n                case TextPointerContext.ElementStart:","sourceCodeStart":983,"sourceCodeEnd":1019,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/PresentationFramework/MS/Internal/PtsHost/ContainerParagraph.cs#L983-L1019","documentation":"During PTS layout, ContainerParagraph.GetParagraph builds a TextParagraph from an element's TextPointer. If the pointer falls before the start of the text container, the workaround check tolerates it only when the element is a TextElement and the pointer is exactly its ContentStart; otherwise the document tree is in a state where a text run exists in an illegal position, and an InvalidOperationException (TextSchema_TextIsNotAllowedInThisContext) is thrown naming the offending element type.","triggerScenarios":"Performing a full-layout pass (formatter.Validate / CreateAndFormatLine drives GetFirstPara/GetNextPara) over a FlowDocument/TextBlock whose content tree violates the text schema — e.g. a TextPointer positioned before ContentStart of a non-TextElement, or corrupted/incoherent element boundaries after programmatic edits.","commonSituations":"Heavy programmatic manipulation of FlowDocument content (inserting runs/inline collections while a previous layout is still pending), sharing a TextPointer across threads, or editing document content during the LayoutUpdated/paging pass.","solutions":["Audit recent programmatic edits to the document for content placed outside valid TextElement boundaries; rebuild the offending element or insert text via TextPointer.InsertTextInRun on positions inside the container.","Defer document mutations until layout is not in progress (Dispatcher.BeginInvoke at background priority after the format pass).","Re-create the FlowDocument content if the tree was deserialized or manipulated externally and pointers may be stale.","If reproducible, capture the element type named in the message and inspect its ContentStart/TextContainer position to find the invalid insert."],"exampleFix":"// before (mutating during layout)\ndoc.Blocks.Add(paragraph); // inside LayoutUpdated handler -> layout walks invalid position\n// after\nDispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() => doc.Blocks.Add(paragraph)));","handlingStrategy":"try-catch","validationCode":"bool pointerIsValid = !(textPointer.TextContainer.Start.CompareTo(textPointer) > 0) || (element is TextElement te && te.ContentStart == textPointer);","typeGuard":"static bool IsTextElementWithValidStart(object e, TextPointer p) => e is TextElement te && te.ContentStart == p;","tryCatchPattern":"try { formatter.Format(documentPage); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"not allowed in this context\")) { RebuildDocumentTree(doc); }","preventionTips":["Do not mutate FlowDocument content while a layout/format pass is in progress","Route all edits through TextPointer/TextRange APIs that respect element boundaries","Defer batched document edits to background Dispatcher priority","Keep TextPointer usage on the thread that owns the text container"],"tags":["wpf","flowdocument","pts-layout","text-schema"],"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-21T21:30:21.729Z"}