dotnet/wpf · error · InvalidOperationException
SR.TypeMetadataCannotChangeAfterUse
Error message
SR.TypeMetadataCannotChangeAfterUse
What it means
PropertyMetadata.DefaultValue's setter throws InvalidOperationException when the metadata instance is Sealed, i.e. it has already been used to register a dependency property or otherwise sealed by the WPF property system. Metadata is frozen after first use so all registered properties share consistent behavior.
Solutions
- Create a new PropertyMetadata instance with the desired DefaultValue instead of mutating the sealed one.
- Use DependencyProperty.AddOwner or OverrideMetadata to supply new metadata for a derived type rather than editing existing metadata.
- Set DefaultValue in the constructor before any Register call, and keep metadata instances private per property.
- Check the Sealed property before mutating and branch to a fresh instance.
Example fix
// before
MyControl.ValueProperty.OverrideMetadata(typeof(MyControl), sharedMetadata);
sharedMetadata.DefaultValue = 42; // InvalidOperationException if sharedMetadata is sealed
// after
MyControl.ValueProperty.OverrideMetadata(typeof(MyControl),
new PropertyMetadata { DefaultValue = 42 }); Defensive patterns
Strategy: validation
Validate before calling
if (metadata.Sealed)
metadata = new PropertyMetadata { DefaultValue = newDefault };
else
metadata.DefaultValue = newDefault; Try / catch
try
{
metadata.DefaultValue = newDefault;
}
catch (InvalidOperationException)
{
// metadata already registered; use OverrideMetadata with a new instance instead
} Prevention
- Treat PropertyMetadata instances as immutable after passing them to Register/OverrideMetadata.
- Never share one static metadata instance across properties you plan to customize individually.
- Set DefaultValue only via the constructor at creation time.
When it happens
Trigger: Setting DefaultValue on a PropertyMetadata instance after it was passed to DependencyProperty.Register/RegisterAttached/RegisterReadOnly (or after Merge sealed it), typically via a shared/static metadata object.
Common situations: Reusing one static PropertyMetadata across multiple dependency properties and then mutating it; overriding defaults at runtime for a property that was already registered; framework code sealing metadata during app startup while later code mutates it.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Image_EncoderNoGlobalMetadata
- Image_OriginalStreamReadOnly
- SR.DefaultValueMayNotBeUnset
- SR.TypeMetadataCannotChangeAfterUse
- Animation_Invalid_DefaultValue
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/5f37c32656ae6f5f.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/WindowsBase/System/Windows/PropertyMetadata.cs:92
public object DefaultValue
{
get
{
if (_defaultValue is not DefaultValueFactory defaultFactory)
{
return _defaultValue;
}
else
{
return defaultFactory.DefaultValue;
}
}
set
{
if (Sealed)
{
throw new InvalidOperationException(SR.TypeMetadataCannotChangeAfterUse);
}
if (value == DependencyProperty.UnsetValue)
{
throw new ArgumentException(SR.DefaultValueMayNotBeUnset);
}
_defaultValue = value;
SetModified(MetadataFlags.DefaultValueModifiedID);
}
}
/// <summary>
/// Returns true if the default value is a DefaultValueFactory
/// </summary>
internal bool UsingDefaultValueFactoryView on GitHub (pinned to 81131a70a4)