dotnet/wpf · error · XamlObjectReaderException

SR.XamlFactoryInvalidXamlNode

Error message

SR.XamlFactoryInvalidXamlNode

What it means

While hoisting namespace declarations to the root of a document (XamlObjectReader factory path), the reader expects to encounter only NamespaceDeclaration nodes before the first StartObject. Any other node type before the start object indicates a malformed or unexpected node stream, so XamlObjectReaderException is thrown.

Solutions

  1. Inspect the node stream before the first StartObject and ensure only NamespaceDeclaration nodes appear there
  2. Regenerate the XAML source so the document starts with namespace declarations followed immediately by the root object
  3. If producing nodes programmatically, fix the producer to emit the StartObject right after namespaces

Example fix

// before: <Value> emitted before root object in node stream
// after: ensure stream is NamespaceDeclaration*, StartObject, ...
Defensive patterns

Strategy: try-catch

Validate before calling

// scan leading nodes yourself before invoking the factory path
while (reader.Read() && reader.NodeType != XamlNodeType.StartObject)
    if (reader.NodeType != XamlNodeType.NamespaceDeclaration) throw new InvalidOperationException($"Unexpected {reader.NodeType} before root object");

Try / catch

try { LoadFactoryXaml(...); } catch (XamlObjectReaderException ex) { Log(ex.Message); /* fall back to re-parsing source XAML */ }

Prevention

When it happens

Trigger: Feeding a XAML node stream into the factory/markup-info path where a node other than a namespace declaration appears before the first StartObject node (e.g. a Value or StartMember preceding the root object).

Common situations: Hand-constructed XamlXmlReader/XamlObjectReader node streams; corrupted or programmatically generated XAML where the root object is not the first non-namespace node; bugs in custom XAML node producers.

Related errors


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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/XamlObjectReader.cs:2899

            // This is kinda fancy-- XamlFactories are converted to XamlReaders, and then the XAML from those
            // readers is supposed to be inserted into the XAML verbatim. The problem is that we are supposed to
            // be a ObjectMarkupInfo, and that implies certain things, like the ability to add a key or
            // a name.
            //
            // So! We shred the XAML into a record; for each member that the XamlReader reports, we create a new
            // MemberMarkupInfo, and then for each subtree under the member we construct either an
            // ValueMarkupInfo or a XamlNodeMarkupInfo to contain the subtree. (The reason we bother
            // to check atom-ness is to make the XAML that we write prettier.)
            //
            public XamlTemplateMarkupInfo(XamlReader reader, SerializerContext context)
            {
                // we hoist all the namespace declarations we can hoist to the root of the document
                // without conflicting any previously defined namespace declarations.
                while (reader.Read() && reader.NodeType != XamlNodeType.StartObject)
                {
                    if (reader.NodeType != XamlNodeType.NamespaceDeclaration)
                    {
                        throw new XamlObjectReaderException(SR.Format(SR.XamlFactoryInvalidXamlNode, reader.NodeType));
                    }

                    if (!context.TryHoistNamespaceDeclaration(reader.Namespace))
                    {
                        nodes.Add(new ValueMarkupInfo{ XamlNode = new XamlNode(XamlNodeType.NamespaceDeclaration, reader.Namespace) });
                    }
                }

                if (reader.NodeType != XamlNodeType.StartObject)
                {
                    throw new XamlObjectReaderException(SR.Format(SR.XamlFactoryInvalidXamlNode, reader.NodeType));
                }

                nodes.Add(new ValueMarkupInfo { XamlNode = new XamlNode(XamlNodeType.StartObject, reader.Type) });
                objectPosition = nodes.Count;

                while (reader.Read())
                {

View on GitHub (pinned to 81131a70a4)