dotnet/wpf · error · ArgumentOutOfRangeException

throw new ArgumentOutOfRangeException(IsHorizontal(_hwnd) ?…

Error message

throw new ArgumentOutOfRangeException(IsHorizontal(_hwnd) ? "horizontalPercent" : "verticalPercent", SR.ScrollBarOutOfRange);

What it means

The ScrollByPercent helper (called from SetScrollPercent) validates the percent and throws ArgumentOutOfRangeException naming horizontalPercent or verticalPercent (chosen by pager orientation) when the value is outside 0..100. It runs after the NoScroll sentinel check, so only concrete percents are range-checked.

Solutions

  1. Clamp the value into [0, 100] (Math.Clamp) before calling SetScrollPercent
  2. Keep NoScroll (-1) as the only out-of-range sentinel accepted
  3. Compute percents as Math.Round(100.0 * position / range) and assert the range

Example fix

// before
scrollPattern.SetScrollPercent(150, ScrollPattern.NoScroll);
// after
double pct = Math.Clamp(computedPercent, 0, 100);
scrollPattern.SetScrollPercent(pct, ScrollPattern.NoScroll);
Defensive patterns

Strategy: validation

Validate before calling

if (pct != ScrollPattern.NoScroll && (pct < 0 || pct > 100))
    throw new ArgumentException($"percent {pct} outside 0..100", nameof(pct));

Type guard

static bool IsValidScrollPercent(double p) => p == ScrollPattern.NoScroll || (p >= 0 && p <= 100);

Try / catch

try { scrollPattern.SetScrollPercent(pct, ScrollPattern.NoScroll); }
catch (ArgumentOutOfRangeException) { pct = Math.Clamp(pct, 0, 100); scrollPattern.SetScrollPercent(pct, ScrollPattern.NoScroll); }

Prevention

When it happens

Trigger: Calling SetScrollPercent with a value < 0 or > 100 on the applicable axis, e.g. 150 or -5 (other than -1/NoScroll which is allowed).

Common situations: Computing a percent from an arithmetic formula (ratio scaling, DPI math) that overflows the 0-100 range; passing percent/100 fractions by mistake.

Related errors


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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/UIAutomation/UIAutomationClientSideProviders/MS/Internal/UnsupportedAutomationProxies/windowspager.cs:421

        #region Private Methods

        private bool IsScrollable()
        {
            return IsVisible(_hwnd, NativeMethods.PGB_BOTTOMORRIGHT) || IsVisible(_hwnd, NativeMethods.PGB_TOPORLEFT);
        }

        // Scrolls the pager by a given percent from its current position.
        private bool ScrollByPercent(double scrollPercent)
        {
            // Check params
            if ((int)scrollPercent == (int)ScrollPattern.NoScroll)
            {
                return true;
            }

            if (scrollPercent < 0 || scrollPercent > 100)
            {
                throw new ArgumentOutOfRangeException(IsHorizontal(_hwnd) ? "horizontalPercent" : "verticalPercent", SR.ScrollBarOutOfRange);
            }

            NativeMethods.Win32Rect rcChild = new NativeMethods.Win32Rect();
            int cRange = ScrollRange (ref rcChild);

            // indicative of an error
            if (cRange < 0)
            {
                return false;
            }

            // Do proper rounding
            int newPos = (int) (cRange * scrollPercent / 100 + 0.5);

            // Sometimes the PGM_SETPOS fails. Try 3 times when this happens
            for (int i = 0; i < 3; i++)
            {
                Misc.ProxySendMessage(_hwnd, NativeMethods.PGM_SETPOS, IntPtr.Zero, new IntPtr(newPos));

View on GitHub (pinned to 81131a70a4)