stride3d/stride · error · InvalidOperationException

A part named ' ' must be present in the ControlTemplate…

Error message

A part named '{MessageContainerPartName}' must be present in the ControlTemplate, and must be of type '{typeof(FlowDocumentScrollViewer)}'.

What it means

MarkdownTextBlock.OnApplyTemplate fetches the mandatory template part 'PART_MessageContainer' and requires it to be a FlowDocumentScrollViewer. When the applied ControlTemplate is missing that part (or names it differently / uses another element type), GetTemplateChild returns null and an InvalidOperationException is thrown.

Solutions

  1. Add <FlowDocumentScrollViewer x:Name="PART_MessageContainer"/> to the ControlTemplate
  2. Verify the part name matches MessageContainerPartName exactly (case-sensitive)
  3. Ensure the part element is a FlowDocumentScrollViewer, not a subclass-less substitute like ContentPresenter
  4. Base your custom template on the library's default template for MarkdownTextBlock

Example fix

<!-- before -->
<ControlTemplate TargetType="mtb:MarkdownTextBlock">
  <Border Background="Transparent"/>
</ControlTemplate>
<!-- after -->
<ControlTemplate TargetType="mtb:MarkdownTextBlock">
  <Border Background="Transparent">
    <FlowDocumentScrollViewer x:Name="PART_MessageContainer"/>
  </Border>
</ControlTemplate>
Defensive patterns

Strategy: validation

Validate before calling

// validate template parts before/after ApplyTemplate in your hosting code
var container = markdownTextBlock.Template?.FindName("PART_MessageContainer", markdownTextBlock) as FlowDocumentScrollViewer;
if (container == null) throw new InvalidOperationException("Custom MarkdownTextBlock template is missing PART_MessageContainer (FlowDocumentScrollViewer)");

Type guard

bool HasValidMarkdownTemplate(MarkdownTextBlock c) => c.Template?.FindName("PART_MessageContainer", c) is FlowDocumentScrollViewer;

Try / catch

try { control.ApplyTemplate(); }
catch (InvalidOperationException ex) { log.Error(ex, "Invalid MarkdownTextBlock template; falling back to default style"); control.Style = null; }

Prevention

When it happens

Trigger: Applying a custom ControlTemplate for MarkdownTextBlock that omits the part named by MessageContainerPartName, names it incorrectly, or hosts an element that is not a FlowDocumentScrollViewer.

Common situations: Re-templating the control for theming; upgrading Stride and copying an outdated template; hand-written Styles without the required part; renaming the part x:Name in XAML.

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 stride3d/stride@96fad776d2 (2026-09-14). Data as JSON: /api/errors/5d907ce27255ab1e. Report an issue: GitHub.

Appendix: source

Thrown at sources/presentation/Stride.Core.Presentation.Wpf/Controls/MarkdownTextBlock.cs:92

        static MarkdownTextBlock()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(MarkdownTextBlock), new FrameworkPropertyMetadata(typeof(MarkdownTextBlock)));
        }

        public MarkdownTextBlock()
        {
            defaultMarkdown = new Lazy<XamlMarkdown>(() => new XamlMarkdown(this));
        }

        /// <inheritdoc/>
        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();

            messageContainer = GetTemplateChild(MessageContainerPartName) as FlowDocumentScrollViewer;
            if (messageContainer == null)
                throw new InvalidOperationException($"A part named '{MessageContainerPartName}' must be present in the ControlTemplate, and must be of type '{typeof(FlowDocumentScrollViewer)}'.");

            ResetMessage();
        }

        private static void BaseUrlChanged([NotNull] DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var control = d as MarkdownTextBlock;
            if (control == null) throw new ArgumentNullException(nameof(control));

            if (e.NewValue != null)
            {
                control.GetMarkdown().BaseUrl = (string)e.NewValue;
            }
            control.ResetMessage();
        }

        private static void HyperlinkCommandChanged([NotNull] DependencyObject d, DependencyPropertyChangedEventArgs e)
        {

View on GitHub (pinned to 96fad776d2)