dotnet/wpf · error · ArgumentOutOfRangeException

InvalidDrawingAttributesWidth

Error message

InvalidDrawingAttributesWidth

What it means

ExtendedPropertySerializer rejects a value assigned to a DrawingAttributes extended property (Width/Height guid) whose double value is NaN, negative-below MinWidth, or above DrawingAttributes.MaxWidth. The library enforces the documented DrawingAttributes width range before persisting to ISF. It is an ArgumentOutOfRangeException naming the offending parameter.

Solutions

  1. Validate the double before assigning: check !double.IsNaN && >= DrawingAttributes.MinWidth && <= DrawingAttributes.MaxWidth
  2. Clamp the value: Math.Max(DrawingAttributes.MinWidth, Math.Min(DrawingAttributes.MaxWidth, value))
  3. Replace NaN with a sane default such as DrawingAttributes.DefaultWidth
  4. Guard upstream data sources (config, files, network) that feed widths

Example fix

// before
attr.AddPropertyData(CustomAttributeSerializer.CurrentWidthGuid, computedWidth); // may be NaN/negative
// after
if (!double.IsNaN(computedWidth) && computedWidth >= DrawingAttributes.MinWidth && computedWidth <= DrawingAttributes.MaxWidth)
    attr.AddPropertyData(CustomAttributeSerializer.CurrentWidthGuid, computedWidth);
else
    attr.Width = DrawingAttributes.DefaultWidth;
Defensive patterns

Strategy: validation

Validate before calling

static bool IsValidWidth(double w) => !double.IsNaN(w) && !double.IsInfinity(w) && w >= System.Windows.Ink.DrawingAttributes.MinWidth && w <= System.Windows.Ink.DrawingAttributes.MaxWidth;

Type guard

static bool IsFiniteInRange(double v, double min, double max) => double.IsFinite(v) && v >= min && v <= max;

Try / catch

try { attr.AddPropertyData(widthGuid, value); }
catch (ArgumentOutOfRangeException) { attr.Width = System.Windows.Ink.DrawingAttributes.DefaultWidth; }

Prevention

When it happens

Trigger: Calling ExtendedPropertySerializer.SaveAsBaseValue or DrawingAttributes extended-property serialization with value = double.NaN, a negative width, or a value > DrawingAttributes.MaxWidth for the Width (or Height-family) guid.

Common situations: Computing a stroke width from user input or math that yields NaN (e.g. 0/0) or negative values; deserializing config or older files with unvalidated widths; unit tests probing boundary values.

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/2567543c5444f627. Report an issue: GitHub.

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/MS/internal/Ink/InkSerializedFormat/CustomAttributeSerializer.cs:868

                if ( value.GetType() != typeof(double) )
                {
                    throw new ArgumentException(SR.Format(SR.InvalidValueType, typeof(double)), nameof(value));
                }

                double dVal = (double)value;

                if (id == KnownIds.StylusHeight)
                {
                    if ( Double.IsNaN(dVal) || dVal < DrawingAttributes.MinHeight || dVal > DrawingAttributes.MaxHeight)
                    {
                        throw new ArgumentOutOfRangeException(nameof(value), SR.InvalidDrawingAttributesHeight);
                    }
                }
                else
                {
                    if (Double.IsNaN(dVal) ||  dVal < DrawingAttributes.MinWidth || dVal > DrawingAttributes.MaxWidth)
                    {
                        throw new ArgumentOutOfRangeException(nameof(value), SR.InvalidDrawingAttributesWidth);
                    }
                }
            }
            else if ( id == KnownIds.Transparency )
            {
                if ( value.GetType() != typeof(byte) )
                {
                    throw new ArgumentException(SR.Format(SR.InvalidValueType, typeof(byte)), nameof(value));
                }

                double dVal = (double)value;
            }
            else
            {
                if ( !UsesEmbeddedTypeInformation(id) )
                {
                    // if this guid used the legacy internal attribute persistence APIs,
                    //      then it doesn't include embedded type information (it's always a byte array)

View on GitHub (pinned to 81131a70a4)