{"record":{"id":"b3a9f754dc0e498b","repo":"dotnet/wpf","slug":"sr-expectedobjectmarkupinfo","errorCode":null,"errorMessage":"SR.ExpectedObjectMarkupInfo","messagePattern":"SR\\.ExpectedObjectMarkupInfo","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/XamlObjectReader.cs","lineNumber":311,"sourceCode":"                            if (child is ObjectMarkupInfo objectInfo && !objectInfo.IsAttributableMarkupExtension)\n                            {\n                                Debug.Assert(false); // should never reach here\n                                return false;\n                            }\n                        }\n\n                        return true;\n                    }\n\n                    // Non-empty Collections are not attributable\n                    if (Children.Count > 1) { return false; }\n\n                    // Empty collections and atoms are attributable\n                    if (Children.Count == 0 || Children[0] is ValueMarkupInfo) { return true; }\n\n                    if (Children[0] is not ObjectMarkupInfo r)\n                    {\n                        throw new InvalidOperationException(SR.ExpectedObjectMarkupInfo);\n                    }\n\n                    return r.IsAttributableMarkupExtension;\n                }\n            }\n\n            public override void FindNamespace(SerializerContext context)\n            {\n                var member = XamlNode.Member;\n                if (MemberRequiresNamespaceHoisting(member))\n                {\n                    context.FindPrefix(member.PreferredXamlNamespace);\n                }\n\n                foreach (var ov in Children)\n                {\n                    ov.FindNamespace(context);\n                }","sourceCodeStart":293,"sourceCodeEnd":329,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/XamlObjectReader.cs#L293-L329","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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)."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":"bool IsAttributableSafe(MemberMarkupInfo m) => m.Children.Count == 0 || m.Children[0] is ValueMarkupInfo || m.Children[0] is ObjectMarkupInfo;\n","tryCatchPattern":"try { attributable = member.IsAttributable; }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"markup\")) { log(memberType); throw; /* internal invariant — surface details */ }","preventionTips":["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."],"tags":["xaml","internal-invariant-violation","wpf"],"backgroundTag":"internal-invariant-violation","analyzedSha":"81131a70a4c573cd62748a5c36908fc4d662daa9","analyzedAt":"2026-09-14T10:12:48.479Z","contentChangedAt":"2026-09-14T10:12:48.479Z","schemaVersion":2},"datasetVersion":"2026-09-21T21:30:21.729Z"}