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
- Inspect the node stream before the first StartObject and ensure only NamespaceDeclaration nodes appear there
- Regenerate the XAML source so the document starts with namespace declarations followed immediately by the root object
- 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
- Never hand-build node streams; derive them from XamlXmlReader
- Validate generated XAML starts with namespaces then a root object
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
- MappingParseError(_scanner.Start, MappingScanner.Ident…
- SR.Format(SR.LengthFormatError, span.ToString())
- SR.Format(SR.NonWhiteSpaceInAddText, s)
- SR.GlyphsClusterMisplacedSeparator
- SR.GlyphsClusterNoMatchingBracket
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)