dotnet/wpf · error · XamlParseException

SR.CantAssignRootInstance

Error message

SR.CantAssignRootInstance

What it means

XamlParseException thrown by XamlObjectWriter.WriteStartObject when a root object instance was pre-supplied (via XamlObjectWriterSettings.RootObjectInstance) and the object writer reaches depth 1, but the root instance's type cannot be assigned to (does not implement/derive from) the XAML type of the root node in the node stream. The library refuses to substitute an incompatible root instance.

Solutions

  1. Make the RootObjectInstance type assignable to the XAML root type (implement the interface or derive from the declared root class).
  2. Change the XAML's root element type so it matches (or is a base of) the supplied root instance's type.
  3. Remove RootObjectInstance if the writer should instantiate the root itself from the node stream.
  4. Verify with SchemaContext.GetXamlType(rootInstance.GetType()).CanAssignTo(rootNodeType) before invoking the load.

Example fix

// before
settings.RootObjectInstance = new Button(); // XAML root is <Window ...>
var writer = new XamlObjectWriter(settings); // throws on WriteStartObject
// after
settings.RootObjectInstance = new Window(); // assignable to declared root type
var writer = new XamlObjectWriter(settings);
Defensive patterns

Strategy: validation

Validate before calling

var declared = schemaContext.GetXamlType(rootNodeType);
if (!schemaContext.GetXamlType(settings.RootObjectInstance.GetType()).CanAssignTo(declared))
    throw new InvalidOperationException("RootObjectInstance type not assignable to XAML root type.");

Type guard

static bool RootAssignable(XamlSchemaContext sc, object rootInstance, XamlType rootType) =>
    rootInstance == null || sc.GetXamlType(rootInstance.GetType())?.CanAssignTo(rootType) == true;

Try / catch

try { xamlServices.Load(writer); }
catch (XamlParseException ex) when (ex.Message.Contains("root")) { RecreateWithoutRootInstance(); }

Prevention

When it happens

Trigger: Setting RootObjectInstance to an object whose CLR type cannot be assigned to the XamlType of the StartObject node being written at LiveDepth == 1, e.g. root instance is a Button while the stream declares a Window root.

Common situations: Pre-assigning a root instance in XamlObjectWriterSettings but loading XAML whose root element is a different type; refactoring XAML root elements without updating RootObjectInstance; plugin-style loading where the supplied instance type drifted from the serialized XAML.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14). Data as JSON: /api/errors/fdc49bafbb7fa83d. Report an issue: GitHub.

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/InfosetObjects/XamlObjectWriter.cs:375

            // A Frame is pushed by either a AddNamespace or a WriteGet/StartObject
            if (_context.CurrentType is not null)
            {
                _context.PushScope();
            }

            _context.CurrentType = xamlType;

            // Don't create the Root Instance if we were given one in the settings.
            // This is an important senario when a XamlObject loads a XamlDefinition of itself
            // in it's constructor.  The instance is already created (that is how we got into
            // the constructor), now don't create the first StartObject use the existing instance.
            //
            if ((_context.LiveDepth == 1) && (_rootObjectInstance is not null))
            {
                XamlType rootType = GetXamlType(_rootObjectInstance.GetType());
                if (!rootType.CanAssignTo(_context.CurrentType))
                {
                    throw new XamlParseException(SR.Format(SR.CantAssignRootInstance,
                        rootType.GetQualifiedName(), xamlType.GetQualifiedName()));
                }

                _context.CurrentInstance = _rootObjectInstance;
                if (_context.CurrentType.IsCollection || _context.CurrentType.IsDictionary)
                {
                    _context.CurrentCollection = _rootObjectInstance;
                }

                Logic_BeginInit(_context);
            }
        }

        public override void WriteEndObject()
        {
            ThrowIfDisposed();

            // Deferring Checking

View on GitHub (pinned to 81131a70a4)