dotnet/wpf · error · InvalidOperationException
SR.ExpectedObjectMarkupInfo
Error message
SR.ExpectedObjectMarkupInfo
What it means
While deciding whether a member's content can be emitted as attribute text (IsAttributable), MemberMarkupInfo expects a single child to be either a ValueMarkupInfo or an ObjectMarkupInfo. A child of any other MarkupInfo kind (e.g. MemberMarkupInfo) violates that invariant, so an InvalidOperationException is thrown — an internal state bug in how the member tree was built.
Solutions
- Inspect the object graph member (constructor arguments / collection content) that contains the malformed child and restructure it so content is a plain value or object.
- Report/fix as an internal invariant violation: dump the object type and member being read when the exception fires.
- Work around by simplifying the type's XAML-serializable surface (e.g. use default constructor + property assignment instead of exotic constructor arguments).
Defensive patterns
Strategy: try-catch
Type guard
bool IsAttributableSafe(MemberMarkupInfo m) => m.Children.Count == 0 || m.Children[0] is ValueMarkupInfo || m.Children[0] is ObjectMarkupInfo;
Try / catch
try { attributable = member.IsAttributable; }
catch (InvalidOperationException ex) when (ex.Message.Contains("markup")) { log(memberType); throw; /* internal invariant — surface details */ } Prevention
- Keep member content (constructor args, collections) as values or objects only; avoid nesting complex property members where attribute text is expected.
- Test custom types with XamlObjectReader round-trips during development, not just XamlXmlWriter.
- Treat this exception as a bug report trigger: capture the object type/member in the handler.
When it happens
Trigger: Reading an object graph where a member's Children contains exactly one node that is neither an ObjectMarkupInfo nor a ValueMarkupInfo while evaluating IsAttributable/IsAttributableMarkupExtension (XamlObjectReader.cs:309-311); typically reached via XamlObjectReader over graphs produced with unusual constructor-argument or collection members.
Common situations: Custom XamlDeferringLoader or markup-extension types producing unexpected node shapes; types whose positional-parameter/constructor-argument content is itself a complex property rather than a value or object; internal invariant breakage after framework changes.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- Animation_ChildMustBeKeyFrame
- Animation_ChildMustBeKeyFrame
- Animation_NoTextChildren
- Animation_NoTextChildren
- ArgumentException: path
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/b3a9f754dc0e498b.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/XamlObjectReader.cs:311
if (child is ObjectMarkupInfo objectInfo && !objectInfo.IsAttributableMarkupExtension)
{
Debug.Assert(false); // should never reach here
return false;
}
}
return true;
}
// Non-empty Collections are not attributable
if (Children.Count > 1) { return false; }
// Empty collections and atoms are attributable
if (Children.Count == 0 || Children[0] is ValueMarkupInfo) { return true; }
if (Children[0] is not ObjectMarkupInfo r)
{
throw new InvalidOperationException(SR.ExpectedObjectMarkupInfo);
}
return r.IsAttributableMarkupExtension;
}
}
public override void FindNamespace(SerializerContext context)
{
var member = XamlNode.Member;
if (MemberRequiresNamespaceHoisting(member))
{
context.FindPrefix(member.PreferredXamlNamespace);
}
foreach (var ov in Children)
{
ov.FindNamespace(context);
}View on GitHub (pinned to 81131a70a4)