dotnet/wpf · error · ArgumentException

SR.Format(SR.TypeMetadataAlreadyRegistered, forType.Name)

Error message

SR.Format(SR.TypeMetadataAlreadyRegistered, forType.Name)

What it means

ProcessOverrideMetadata throws this ArgumentException when metadata for the given type has already been registered for this DependencyProperty (the _metadataMap slot for the type's Id is not UnsetValue). Each type may have its metadata overridden at most once per property.

Solutions

  1. Remove the duplicate OverrideMetadata call so each (property, type) pair is overridden exactly once
  2. Guard the call with a static bool 'metadataInitialized' flag to make it idempotent
  3. If two sources must both customize metadata, merge their values into a single FrameworkPropertyMetadata and register it in one call

Example fix

// before
static MyControl()
{
    FooProperty.OverrideMetadata(typeof(MyControl), new PropertyMetadata(1));
}
static MyControl() // partial class: runs duplicate registration
{
    FooProperty.OverrideMetadata(typeof(MyControl), new PropertyMetadata(2)); // throws
}
// after
private static bool _initialized;
static MyControl()
{
    if (_initialized) return;
    _initialized = true;
    FooProperty.OverrideMetadata(typeof(MyControl), new PropertyMetadata(2));
}
Defensive patterns

Strategy: validation

Validate before calling

private static bool _metaDone;
if (!_metaDone)
{
    dp.OverrideMetadata(typeof(MyControl), meta);
    _metaDone = true;
}

Try / catch

try { dp.OverrideMetadata(typeof(MyControl), meta); }
catch (ArgumentException) { /* metadata already registered: treat as idempotent no-op */ }

Prevention

When it happens

Trigger: Calling OverrideMetadata twice for the same (property, forType) pair; calling it again in a static constructor that runs more than once via reflection/re-invocation; two base classes in a hierarchy both overriding metadata for the same intermediate type.

Common situations: Duplicate static constructors in partial classes both overriding metadata; merging code from two libraries that both override metadata of the same DP for the same type; unit tests re-registering metadata repeatedly.

Understand the failure class

Background: "already exists" / EEXIST / FileAlreadyExistsException: what the 'file already exists' error means and how to fix it — this error's family across 37 libraries.

Related errors


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

Appendix: source

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

        /// method is called to actually update the data structures.
        /// </summary>
        private void ProcessOverrideMetadata(
            Type forType,
            PropertyMetadata typeMetadata,
            DependencyObjectType dType,
            PropertyMetadata baseMetadata)
        {
            // Store per-Type metadata for this property. Locks only on Write.
            // Datastructure guaranteed to be valid for non-locking readers
            lock (Synchronized)
            {
                if (DependencyProperty.UnsetValue == _metadataMap[dType.Id])
                {
                    _metadataMap[dType.Id] = typeMetadata;
                }
                else
                {
                    throw new ArgumentException(SR.Format(SR.TypeMetadataAlreadyRegistered, forType.Name));
                }
           }

            // Merge base's metadata into this metadata
            // CALLBACK
            typeMetadata.InvokeMerge(baseMetadata, this);

            // Type metadata may no longer change (calls OnApply)
            typeMetadata.Seal(this, forType);

            if (typeMetadata.IsInherited)
            {
                _packedData |= Flags.IsPotentiallyInherited;
            }

            if (typeMetadata.DefaultValueWasSet() && (typeMetadata.DefaultValue != DefaultMetadata.DefaultValue))
            {
                _packedData |= Flags.IsDefaultValueChanged;

View on GitHub (pinned to 81131a70a4)