dotnet/maui · error · InvalidOperationException

RootComponent requires a value for its Selector property, bu

Error message

RootComponent requires a value for its Selector property, but no value was set.

What it means

The WPF RootComponent.AddToWebViewManagerAsync validates Selector is non-empty before calling AddRootComponentAsync on the WebView2WebViewManager. This mirrors the MAUI RootComponent pattern: since WPF allows XAML instantiation with parameterless constructors, properties are validated at add-time rather than construction-time. A null Selector means there is no DOM insertion point for the component.

Source

Thrown at src/BlazorWebView/src/Wpf/RootComponent.cs:40

		/// <summary>
		/// Gets or sets the type of the root component. This type must implement <see cref="IComponent"/>.
		/// </summary>
		public Type ComponentType { get; set; } = default!;

		/// <summary>
		/// Gets or sets an optional dictionary of parameters to pass to the root component.
		/// </summary>
		public IDictionary<string, object?>? Parameters { get; set; }

		internal Task AddToWebViewManagerAsync(WebViewManager webViewManager)
		{
			// As a characteristic of XAML,we can't rely on non-default constructors. So we have to
			// validate that the required properties were set. We could skip validating this and allow
			// the lower-level renderer code to throw, but that would be harder for developers to understand.

			if (string.IsNullOrWhiteSpace(Selector))
			{
				throw new InvalidOperationException($"{nameof(RootComponent)} requires a value for its {nameof(Selector)} property, but no value was set.");
			}

			if (ComponentType is null)
			{
				throw new InvalidOperationException($"{nameof(RootComponent)} requires a value for its {nameof(ComponentType)} property, but no value was set.");
			}

			var parameterView = Parameters == null ? ParameterView.Empty : ParameterView.FromDictionary(Parameters);
			return webViewManager.AddRootComponentAsync(ComponentType, Selector, parameterView);
		}

		internal Task RemoveFromWebViewManagerAsync(WebView2WebViewManager webviewManager)
		{
			return webviewManager.RemoveRootComponentAsync(Selector);
		}
	}
}

View on GitHub (pinned to f377ff1c5e)

Solutions

  1. Set the Selector property on the RootComponent before adding it: rc.Selector = "#app";
  2. In XAML: <blazor:RootComponent Selector="#app" ComponentType="{x:Type local:MyComponent}" />.
  3. If Selector comes from a binding, ensure the source property is non-null: use FallbackValue or TargetNullValue.
  4. Validate dynamically created RootComponents before adding to the collection.

Example fix

// before (XAML)
<blazor:RootComponent ComponentType="{x:Type local:MyComponent}" />
// after
<blazor:RootComponent Selector="#app" ComponentType="{x:Type local:MyComponent}" />
Defensive patterns

Strategy: validation

Validate before calling

// Validate Selector before adding
if (string.IsNullOrWhiteSpace(rootComponent.Selector))
{
    throw new InvalidOperationException("RootComponent.Selector must be set.");
}
await rootComponent.AddToWebViewManagerAsync(webViewManager);

Type guard

static bool IsValidWpfRootComponent(RootComponent rc)
{
    return !string.IsNullOrWhiteSpace(rc?.Selector);
}

Prevention

When it happens

Trigger: A WPF RootComponent with an unset or whitespace Selector has AddToWebViewManagerAsync called — either explicitly or when the BlazorWebView collects RootComponents during its initialization pass.

Common situations: XAML RootComponent declaration missing the Selector attribute or bound to a null value; dynamically creating RootComponent objects and forgetting to set Selector; property binding that resolves to null at runtime; copy-paste error where Selector was removed during refactoring.

Related errors


AI-assisted analysis of dotnet/maui@f377ff1c5e (2026-08-13). Data as JSON: /api/errors/369b6f77b1c9f291. Report an issue: GitHub.