dotnet/wpf · error · ArgumentException

Maximum number of strokes is two.

Error message

Maximum number of strokes is two.

What it means

NativeRecognizer.Recognize performs gesture recognition on at most two strokes at a time, matching the native recognizer's design. Passing a StrokeCollection with more than two strokes throws ArgumentException (SR.StrokeCollectionCountTooBig). Argument validation is duplicated here even though GestureRecognizer validates it, because the method is ThreadSafeOptional.

Solutions

  1. Split the StrokeCollection into chunks of at most 2 strokes and call Recognize per chunk
  2. Pass only the stroke(s) from the gesture event (e.g. e.Strokes on InkCanvasGestureEventArgs)
  3. Remove the extra strokes before calling Recognize
  4. If more strokes must be analyzed, run recognition incrementally and merge results

Example fix

// before
recognizer.Recognize(inkCanvas.Strokes);
// after
foreach (var s in inkCanvas.Strokes) { var result = recognizer.Recognize(new StrokeCollection { s }); }
Defensive patterns

Strategy: validation

Validate before calling

if (strokes == null) throw new ArgumentNullException(nameof(strokes));
if (strokes.Count > 2) throw new ArgumentException("Recognize accepts at most 2 strokes", nameof(strokes));

Type guard

static bool CanRecognize(StrokeCollection s) => s != null && s.Count >= 1 && s.Count <= 2;

Try / catch

try { return recognizer.Recognize(strokes); }
catch (ArgumentException) { return Array.Empty<GestureRecognitionResult>(); }

Prevention

When it happens

Trigger: Calling Recognize with a StrokeCollection whose Count exceeds 2 — e.g. passing an entire InkCanvas.Strokes collection instead of the one or two strokes captured in a gesture event.

Common situations: Developers wiring InkCanvas gesture handlers and forwarding the whole stroke collection; batching strokes for recognition; misunderstanding that recognition is per-stroke-pair (e.g. for two-stroke gestures like 'check').

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/379e11f065677796. Report an issue: GitHub.

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/MS/internal/Ink/GestureRecognizer/NativeRecognizer.cs:125

        }

        /// <summary>
        /// Recognize the strokes.
        /// </summary>
        /// <param name="strokes"></param>
        /// <returns></returns>
        internal GestureRecognitionResult[] Recognize(StrokeCollection strokes)
        {
            ObjectDisposedException.ThrowIf(_disposed, typeof(NativeRecognizer));

            //
            // note that we validate this argument from GestureRecognizer 
            // but since this is marked TAS, we want to do it here as well
            //
            ArgumentNullException.ThrowIfNull(strokes);
            if (strokes.Count > 2)
            {
                throw new ArgumentException(SR.StrokeCollectionCountTooBig, nameof(strokes));
            }

            // Create an empty result.
            GestureRecognitionResult[] recResults = Array.Empty<GestureRecognitionResult>();

            if ( strokes.Count == 0 )
            {
                return recResults;
            }

            int hr = 0;

            try
            {
                // Reset the context
                hr = MS.Win32.Recognizer.UnsafeNativeMethods.ResetContext(_hContext);
                if (HRESULT.Failed(hr))
                {

View on GitHub (pinned to 81131a70a4)