dotnet/wpf · error · InvalidOperationException

SR.Format(SR.TooManyDependencyProperties…

Error message

SR.Format(SR.TooManyDependencyProperties, "ConstantProperty")

What it means

Same global-index overflow as the ownerType variant, but raised when ownerType is null — i.e. the overflow occurred while registering something without an owner type, reported with the placeholder name "ConstantProperty". GlobalIndexCount exceeded GlobalIndexMask, so no unique global index can be assigned.

Solutions

  1. Reduce total number of registered DPs in the process; audit libraries doing dynamic registration
  2. Replace dynamic DP-per-item patterns with attached properties or plain dictionaries
  3. Profile with a debugger/ETW to find who registers tens of thousands of DPs and fix that library

Example fix

// before
// thousands of generated static types each Register-ing DPs at module load
var dp = DependencyProperty.Register(name, typeof(object), ownerType); // called in loop
// after
var valueCache = new Dictionary<object, object>(); // plain storage
// or a single attached property:
public static readonly DependencyProperty ValueProperty =
    DependencyProperty.RegisterAttached("Value", typeof(object), typeof(Holder));
Defensive patterns

Strategy: validation

Validate before calling

// audit total DP registrations before adding more
if (Interlocked.Increment(ref registeredDpCount) > 32000)
    throw new InvalidOperationException("Global DP index exhausted");

Try / catch

try { RegisterInternally(name, value); }
catch (InvalidOperationException) { /* overflow: degrade to non-DP storage */ }

Prevention

When it happens

Trigger: Exceeding ~32767 registered dependency properties in the AppDomain via a registration path that passes a null ownerType into GetUniqueGlobalIndex (internal constant/property registration paths).

Common situations: Same as the ownerType overflow: dynamic DP creation at scale, plugin systems, codegen frameworks; the null-owner variant usually indicates an internal registration path, so look at total DP counts in the process.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


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

Appendix: source

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

            _packedData = packedData;
        }

        // Synchronized: Covered by DependencyProperty.Synchronized
        internal static int GetUniqueGlobalIndex(Type ownerType, string name)
        {
            // Prevent GlobalIndex from overflow. DependencyProperties are meant to be static members and are to be registered
            // only via static constructors. However there is no cheap way of ensuring this, without having to do a stack walk. Hence
            // concievably people could register DependencyProperties via instance methods and therefore cause the GlobalIndex to
            // overflow. This check will explicitly catch this error, instead of silently malfuntioning.
            if (GlobalIndexCount >= (int)Flags.GlobalIndexMask)
            {
                if (ownerType != null)
                {
                    throw new InvalidOperationException(SR.Format(SR.TooManyDependencyProperties, ownerType.Name + "." + name));
                }
                else
                {
                    throw new InvalidOperationException(SR.Format(SR.TooManyDependencyProperties, "ConstantProperty"));
                }
            }

            // Covered by Synchronized by caller
            return GlobalIndexCount++;
        }

        /// <summary>
        /// This is the callback designers use to participate in the computation of property
        /// values at design time. Eg. Even if the author sets Visibility to Hidden, the designer
        /// wants to coerce the value to Visible at design time so that the element doesn't
        /// disappear from the design surface.
        /// </summary>
        internal CoerceValueCallback DesignerCoerceValueCallback
        {
            get {  return _designerCoerceValueCallback; }
            set
            {

View on GitHub (pinned to 81131a70a4)