dotnet/wpf · error · ArgumentOutOfRangeException

SR.ScrollBarOutOfRange

Error message

SR.ScrollBarOutOfRange

What it means

WindowsTab.SetScrollPercent validates the horizontal scroll percent and throws ArgumentOutOfRangeException(SR.ScrollBarOutOfRange) when the value is outside 0..100 (and not ScrollPattern.NoScroll). Scroll percentages must be expressed as a percentage of the total scrollable range, so negative values or values above 100 are meaningless.

Solutions

  1. Clamp the percentage: Math.Max(0.0, Math.Min(100.0, percent)) before calling.
  2. Use ScrollPattern.NoScroll (-1) explicitly for 'do not scroll' instead of 0 or negative sentinels.
  3. Verify the value fits 0..100 after any normalization/conversion from pixel offsets.

Example fix

// before
tab.SetScrollPercent(150.0, -1);
// after
double pct = Math.Clamp(150.0, 0.0, 100.0);
tab.SetScrollPercent(pct, ScrollPattern.NoScroll);
Defensive patterns

Strategy: validation

Validate before calling

if (percent != ScrollPattern.NoScroll && (percent < 0 || percent > 100))
    throw new ArgumentException("percent must be 0..100 or ScrollPattern.NoScroll");

Type guard

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

Try / catch

try { sp.SetScrollPercent(h, v); }
catch (ArgumentOutOfRangeException ex) { /* ex.ParamName == "horizontalPercent" */ }

Prevention

When it happens

Trigger: Calling ScrollPattern.SetScrollPercent(h, v) on a WindowsTab proxy where horizontalPercent < 0 or horizontalPercent > 100, and it is not ScrollPattern.NoScroll.

Common situations: Computing scroll positions with float rounding that yields 100.4; passing pixel positions instead of percentages; copy-pasted code using -1 as a sentinel other than ScrollPattern.NoScroll.

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/1c3c8c866779670f. Report an issue: GitHub.

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/UIAutomation/UIAutomationClientSideProviders/MS/Internal/AutomationProxies/WindowsTab.cs:492

                throw new ElementNotEnabledException();
            }

            if (!IsScrollable())
            {
                throw new InvalidOperationException(SR.OperationCannotBePerformed);
            }

            if ((int)verticalPercent != (int)ScrollPattern.NoScroll)
            {
                throw new InvalidOperationException(SR.OperationCannotBePerformed);
            }
            else if ((int)horizontalPercent == (int)ScrollPattern.NoScroll)
            {
                return;
            }
            else if (horizontalPercent < 0 || horizontalPercent > 100)
            {
                throw new ArgumentOutOfRangeException(nameof(horizontalPercent), SR.ScrollBarOutOfRange);
            }

            // Get up/down control's hwnd
            IntPtr updownHwnd = this.GetUpDownHwnd ();

            if (updownHwnd == IntPtr.Zero)
            {
                throw new InvalidOperationException(SR.OperationCannotBePerformed);
            }

            // Get available range
            int range = Misc.ProxySendMessageInt(updownHwnd, NativeMethods.UDM_GETRANGE, IntPtr.Zero, IntPtr.Zero);
            int minPos = NativeMethods.Util.HIWORD(range);
            int maxPos = NativeMethods.Util.LOWORD(range);

            // Calculate new position
            int newPos = (int) Math.Round ((maxPos - minPos) * horizontalPercent / 100) + minPos;

View on GitHub (pinned to 81131a70a4)