dotnet/wpf · error · XamlObjectReaderException
SR.ObjectReaderTypeCannotRoundtrip
Error message
SR.ObjectReaderTypeCannotRoundtrip
What it means
XamlObjectReader throws this during round-trip validation when an object's type cannot be represented in XAML at all — the type has no usable constructor/member representation for markup (and is not a nested type, which gets a different message). The reader aborts because writing the graph as XAML would be impossible.
Solutions
- Give the type a public parameterless constructor and settable public properties
- Add a TypeConverter (with ConvertFrom/ConvertTo) so the value round-trips via attribute syntax
- Replace the value with a XAML-representable type before reading
- Skip/omit the offending member from the object graph
Example fix
// before: type with only internal ctor, no converter
// after
public class Point2 { public Point2() { } public double X { get; set; } public double Y { get; set; } } Defensive patterns
Strategy: validation
Validate before calling
bool Roundtrippable(Type t) => t.GetConstructor(Type.EmptyTypes) != null || t.GetConstructors().Any(c => c.GetParameters().Length > 0) && !t.IsNested && t.IsVisible;
if (!Roundtrippable(obj.GetType())) throw new InvalidOperationException("Type cannot roundtrip via XAML"); Type guard
bool CanRoundtrip(Type t) => !t.IsNested && t.IsVisible && (t.GetConstructor(Type.EmptyTypes) != null || t.GetConvertFrom != null); // adjust: use TypeConverter check // practical guard: bool HasConverterOrDefaultCtor(Type t) => !t.IsNested && (t.GetConstructor(Type.EmptyTypes) != null || TypeDescriptor.GetConverter(t).CanConvertFrom(typeof(string)));
Try / catch
try { using var r = new XamlObjectReader(obj); ... } catch (XamlObjectReaderException ex) when (ex.Message.Contains("TypeCannotRoundtrip")) { /* substitute or omit value */ } Prevention
- Give XAML-facing types public default ctors and settable properties
- Add TypeConverters for types expressible only as strings/extensions
- Audit third-party values in graphs before XAML round-tripping
When it happens
Trigger: new XamlObjectReader(obj) where CheckTypeCanRoundtrip determines a XamlType in the graph lacks a valid instantiation path (no default ctor, no matching ctor/arguments, no converter/extension representation).
Common situations: Graphs containing types designed purely for code (e.g. delegate-bearing, generic-closed types without converters, internal-only types); third-party objects not designed for markup round-tripping; types without TypeConverters used in collections.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- ArgumentNullException(nameof(writer))
- InvalidOperationException(SR.Format(SR.XamlTypeNameCannotGet…
- (no message - parameterless InvalidOperationException)
- SR.Format(SR.DeferringLoaderNoSave…
- SR.Format(SR.MarkupWriter_CannotSerializeGenerictype…
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/55354a74dbb50a69.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/XamlObjectReader.cs:1730
{
foreach (var property in objInfo.Properties)
{
if (((MemberMarkupInfo)property).IsFactoryMethod && !xamlType.UnderlyingType.IsNested)
{
// this is the case when the class has no public constructor we can use but contains a factory method
// and the class is not nested
return;
}
}
if (xamlType.UnderlyingType.IsNested)
{
throw new XamlObjectReaderException(SR.Format(SR.ObjectReaderTypeIsNested, xamlType.Name));
}
else
{
throw new XamlObjectReaderException(SR.Format(SR.ObjectReaderTypeCannotRoundtrip, xamlType.Name));
}
}
}
public void AssignName(SerializerContext context)
{
if (Name is null)
{
Name = context.AllocateIdentifier();
AddNameProperty(context);
}
}
public void AssignName(string name, SerializerContext context)
{
if (Name is null)
{
Name = name;View on GitHub (pinned to 81131a70a4)