dotnet/wpf · error · ArgumentException

SR.TypeMetadataAlreadyInUse

Error message

SR.TypeMetadataAlreadyInUse

What it means

OverrideMetadata rejects a typeMetadata instance that has already been sealed. Metadata becomes sealed when first used (registered or overridden); reusing the same PropertyMetadata object for a second OverrideMetadata call is not allowed because the property system mutates and freezes it.

Solutions

  1. Create a new PropertyMetadata (or derived) instance for each OverrideMetadata call.
  2. If defaults must be shared, share the default value object, not the metadata instance.
  3. Call OverrideMetadata only once per (property, forType) pair.

Example fix

// before
private static readonly PropertyMetadata SharedMeta = new PropertyMetadata(5);
A.OverrideMetadata(WidthProperty, SharedMeta);
B.OverrideMetadata(WidthProperty, SharedMeta); // throws
// after
A.OverrideMetadata(WidthProperty, new PropertyMetadata(5));
B.OverrideMetadata(WidthProperty, new PropertyMetadata(5));
Defensive patterns

Strategy: validation

Validate before calling

if (metadata.Sealed) throw new InvalidOperationException("Metadata instance already sealed; create a new one");

Type guard

static bool IsReusableMetadata(PropertyMetadata m) => !m.Sealed;

Prevention

When it happens

Trigger: Sharing one PropertyMetadata instance across two OverrideMetadata calls, or calling OverrideMetadata with the same metadata that was passed to Register.

Common situations: Static readonly shared metadata fields reused for several properties/types; refactoring that hoists a metadata literal into a shared variable.

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


AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14). Data as JSON: /api/errors/7728a4a501e8dda4. Report an issue: GitHub.

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/WindowsBase/System/Windows/DependencyProperty.cs:455


        /// <summary>
        ///     Parameter validation for OverrideMetadata, includes code to force
        /// all base classes of "forType" to register their metadata so we know
        /// what we are overriding.
        /// </summary>
        private void SetupOverrideMetadata(
                Type forType,
                PropertyMetadata typeMetadata,
            out DependencyObjectType dType,
            out PropertyMetadata baseMetadata )
        {
            ArgumentNullException.ThrowIfNull(forType);
            ArgumentNullException.ThrowIfNull(typeMetadata);

            if (typeMetadata.Sealed)
            {
                throw new ArgumentException(SR.TypeMetadataAlreadyInUse);
            }

            if (!typeof(DependencyObject).IsAssignableFrom(forType))
            {
                throw new ArgumentException(SR.Format(SR.TypeMustBeDependencyObjectDerived, forType.Name));
            }

            // Ensure default value is a correct value (if it was supplied,
            // otherwise, the default value will be taken from the base metadata
            // which was already validated)
            if (typeMetadata.IsDefaultValueModified)
            {
                // Will throw ArgumentException if fails.
                ValidateMetadataDefaultValue( typeMetadata, PropertyType, Name, ValidateValueCallback );
            }

            // Force all base classes to register their metadata
            dType = DependencyObjectType.FromSystemType(forType);

View on GitHub (pinned to 81131a70a4)