dotnet/wpf · error · InvalidOperationException
SR.ParserCantGetDPOrPi
Error message
SR.ParserCantGetDPOrPi: {0} What it means
BamlReader.GetPropertyCustomRecordInfo throws this when a BAML attribute record resolves to neither a DependencyProperty nor a CLR PropertyInfo. The reader reflected over attrInfo.OwnerType for the property name and found no match, so the property in the BAML stream cannot be applied and parsing fails with InvalidOperationException.
Solutions
- Rebuild the project so the BAML is regenerated against the currently referenced assembly versions.
- Restore the missing/renamed property on the owner type or add a compatibility property.
- Pin the dependency assembly to the exact version the XAML was compiled against (binding redirect or explicit reference).
- Check that the property is public and settable (get/set accessors) so GetProperty can find it.
Example fix
// before: property removed in v2 of the library
public class MyControl { /* Text renamed to Caption */ }
// after
public class MyControl {
public string Caption { get; set; }
[Obsolete("Use Caption")]
public string Text { get => Caption; set => Caption = value; }
} Defensive patterns
Strategy: validation
Validate before calling
// verify the property exists on the owner type before reading BAML referencing it
var pi = ownerType.GetProperty(attrName, BindingFlags.Public | BindingFlags.Instance);
if (pi == null && DependencyPropertyHelper.GetValueSource(owner, dp).BaseValueSource == BaseValueSource.Unknown)
throw new InvalidOperationException($"'{ownerType.Name}.{attrName}' does not exist at runtime; rebuild BAML against current assemblies."); Type guard
bool PropertyResolves(Type ownerType, string name) =>
ownerType != null && (ownerType.GetProperty(name) != null ||
ownerType.GetFields(BindingFlags.Public | BindingFlags.Static).Any(f => f.FieldType == typeof(DependencyProperty) && f.Name == name + "Property")); Try / catch
try { reader.Read(); }
catch (InvalidOperationException ex) when (ex.Message.Contains("DP") || ex.Message.Contains("property")) {
log.LogError($"BAML property '{info?.Name}' no longer exists on its owner type — version mismatch.");
} Prevention
- Pin dependency versions with explicit references/binding redirects.
- Never delete public properties used in XAML without a compatibility shim.
- Recompile all XAML after upgrading control libraries.
- CI check: load all compiled BAML resources in a smoke test.
When it happens
Trigger: Reading BAML where attrInfo.DP was null and OwnerType.GetProperty(attrInfo.Name) returned null — the named property does not exist on the owner type (renamed, removed, or from a different version of the assembly).
Common situations: Runtime references a different version of a control library than the one the XAML was compiled against (property was renamed or deleted); partial-trust reflection failing to see the property; typo scenarios baked into old compiled BAML after an API breaking change.
Understand the failure class
Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.
Related errors
- SR.BamlReaderNoOwnerType
- SR.Format(SR.UnknownBamlRecord, recordType)
- SR.ParserBamlVersion
- SR.ParserUnknownBaml
- Can't Assign to Known Type attributes
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/6519349cbcb4b30e.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Markup/BamlReader.cs:1026
// order varies.
// It's probably more correct to walk up the base class
// tree calling GetProperty with the DeclaredOnly flag.
PropertyInfo[] infos = attrInfo.OwnerType.GetProperties(
BindingFlags.Instance | BindingFlags.Public);
for (int i = 0; i < infos.Length; i++)
{
if (infos[i].Name == attrInfo.Name)
{
attrInfo.PropInfo = infos[i];
break;
}
}
}
if (attrInfo.PropInfo == null)
{
throw new InvalidOperationException(SR.Format(SR.ParserCantGetDPOrPi, info.Name));
}
}
}
// If we have a property, then get its type and call GetCustomValue,
// which uses the XamlSerializer to turn the binary data into a
// real object
Type propertyType = attrInfo.GetPropertyType();
string propertyName = attrInfo.Name;
short sid = bamlRecord.SerializerTypeId;
// if a Setter of Trigger's Property property is being set, then its value is always
// a DP. Get the attribInfo of this DP property from the ValueId read into the custom
// property record and resolve it into an actual DP instance.
if (sid == (short)KnownElements.DependencyPropertyConverter)
{
Type declaringType = null;
_propertyDP = _bamlRecordReader.GetCustomDependencyPropertyValue(bamlRecord, out declaringType);View on GitHub (pinned to 81131a70a4)