AvaloniaUI/Avalonia · error · InvalidOperationException

Invalid render scaling value {scaling}

Error message

Invalid render scaling value {scaling}

What it means

ValidateScaling throws when the render/DPI scaling factor is zero, negative, or non-finite (NaN/Infinity). LayoutHelper.ValidateScaling guards every layout hot path so that a bogus scaling value never propagates into pixel-snapping math (RoundTo8Digits) which would produce corrupt layout geometry. A valid scaling value must be a strictly-positive finite double.

Source

Thrown at src/Avalonia.Base/Layout/LayoutHelper.cs:267

            return dpiScale == 1.0 ?
                Math.Ceiling(value) :
                Math.Ceiling(RoundTo8Digits(value) * dpiScale) / dpiScale;
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        private static double RoundTo8Digits(double value)
        {
            // Round the value to avoid FP errors. This is needed because if `value` has a floating
            // point precision error (e.g. 79.333333333333343) then when it's multiplied by
            // `dpiScale` and rounded up, it will be rounded up to a value one greater than it
            // should be.
            return Math.Round(value, 8, MidpointRounding.ToZero);
        }

        internal static double ValidateScaling(double scaling)
        {
            if (MathUtilities.IsNegativeOrNonFinite(scaling) || MathUtilities.IsZero(scaling))
                throw new InvalidOperationException($"Invalid render scaling value {scaling}");

            if (MathUtilities.IsOne(scaling))
            {
                // Ensure we've got exactly 1.0 and not an approximation,
                // so we don't have to use MathUtilities.IsOne in various layout hot paths.
                return 1.0;
            }

            return scaling;
        }
    }
}

View on GitHub (pinned to 11c5427268)

Solutions

  1. Check the platform DPI scale provider implementation — it must return a strictly positive finite value.
  2. In tests/headless scenarios, ensure the test host (e.g. Avalonia.Headless) is configured and provides a valid scale.
  3. Guard the scaling value before it reaches layout: if non-positive or non-finite, substitute a safe default like 1.0.
  4. Inspect the call stack to find which platform/render layer supplied the degenerate value and fix it at the source.

Example fix

// before
double scale = GetScaleFromPlatform(); // returns 0 or NaN in headless

// after
double scale = GetScaleFromPlatform();
if (double.IsNaN(scale) || scale <= 0) scale = 1.0;
Defensive patterns

Strategy: validation

Validate before calling

static double SafeScale(double scale) =>
    double.IsNaN(scale) || double.IsInfinity(scale) || scale <= 0 ? 1.0 : scale;

// usage before any layout/render code expecting a scale
var safe = SafeScale(reportedScale);

Try / catch

try
{
    LayoutHelper.ValidateScaling(scaling);
}
catch (InvalidOperationException)
{
    scaling = 1.0; // fall back to identity scale
    LayoutHelper.ValidateScaling(scaling);
}

Prevention

When it happens

Trigger: An internal or platform call to LayoutHelper.ValidateScaling(scaling) where scaling is 0, negative, NaN, or Infinity. Typically reached during layout/render setup when the platform reports an invalid DPI scale, or when a custom render target returns a degenerate scaling value.

Common situations: Headless/server environment where the platform DPI provider returns 0. A misconfigured test environment or mock platform returning NaN. A monitor/reporting edge case on certain Linux/Wayland setups returning unexpected scale. Passing `double.NaN` through a scaling binding.

Related errors


AI-assisted analysis of AvaloniaUI/Avalonia@11c5427268 (2026-08-13). Data as JSON: /api/errors/3aed6d4a49141ae7. Report an issue: GitHub.