dotnet/wpf · error · ArgumentException

SR.InvalidStylusPointDescriptionButtonsMustBeLast

Error message

SR.InvalidStylusPointDescriptionButtonsMustBeLast

What it means

The StylusPointDescription constructor enforces that all button properties are placed last in the collection, after every non-button property. Once a button has been seen in the iteration, any subsequent non-button property triggers this ArgumentException, because the internal layout expects data axes followed by button bits.

Solutions

  1. Reorder so all non-button StylusPointPropertyInfos come first (after the mandatory X, Y, NormalPressure) and all buttons come last.
  2. Partition the collection with LINQ: nonButtons.Concat(buttons) before constructing.
  3. Check each info's IsButton flag; WPF's TipButton/BarrelButton properties have IsButton true, custom axes false.

Example fix

// before
var desc = new StylusPointDescription(new[]{ x, y, pressure, tipButton, tiltX });
// after
var desc = new StylusPointDescription(new[]{ x, y, pressure, tiltX, tipButton });
Defensive patterns

Strategy: validation

Validate before calling

bool buttonsLast = !infos.Skip(3).Select((i, idx) => (i, idx))
    .SkipWhile(t => !t.i.IsButton)
    .Any(t => !t.i.IsButton); // any non-button after first button is invalid

Try / catch

try { var desc = new StylusPointDescription(infos); }
catch (ArgumentException) { var ordered = infos.Take(3).Concat(infos.Skip(3).Where(i => !i.IsButton)).Concat(infos.Skip(3).Where(i => i.IsButton)).ToArray(); desc = new StylusPointDescription(ordered); }

Prevention

When it happens

Trigger: Calling new StylusPointDescription(infos) where a non-button StylusPointPropertyInfo (IsButton == false) appears after any button property (IsButton == true) in the collection.

Common situations: Appending custom axis properties (e.g. tilt, twist) after button properties when building a description; concatenating a custom-axis list onto a device list that already ended with buttons; re-sorting the collection alphabetically which moves buttons before some axes.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Input/Stylus/Common/StylusPointDescription.cs:82

            seenIds.Add(StylusPointPropertyIds.NormalPressure);

            int buttonCount = 0;
            for (int x = RequiredCountOfProperties; x < infos.Count; x++)
            {
                if (seenIds.Contains(infos[x].Id))
                {
                    throw new ArgumentException(SR.InvalidStylusPointDescriptionDuplicatesFound, nameof(stylusPointPropertyInfos));
                }
                if (infos[x].IsButton)
                {
                    buttonCount++;
                }
                else
                {
                    //this is not a button, make sure we haven't seen one before
                    if (buttonCount > 0)
                    {
                        throw new ArgumentException(SR.InvalidStylusPointDescriptionButtonsMustBeLast, nameof(stylusPointPropertyInfos));
                    }
                }
                seenIds.Add(infos[x].Id);
            }
            if (buttonCount > MaximumButtonCount)
            {
                throw new ArgumentException(SR.InvalidStylusPointDescriptionTooManyButtons, nameof(stylusPointPropertyInfos));
            }

            _buttonCount = buttonCount;
            _stylusPointPropertyInfos = infos.ToArray();
        }

        /// <summary>
        /// StylusPointDescription
        /// </summary>
        /// <param name="stylusPointPropertyInfos">stylusPointPropertyInfos</param>
        /// <param name="originalPressureIndex">originalPressureIndex - does the digitizer really support pressure?  If so, the index this was at</param>

View on GitHub (pinned to 81131a70a4)