{"record":{"id":"379e11f065677796","repo":"dotnet/wpf","slug":"maximum-number-of-strokes-is-two","errorCode":null,"errorMessage":"Maximum number of strokes is two.","messagePattern":"Maximum number of strokes is two\\.","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/PresentationCore/MS/internal/Ink/GestureRecognizer/NativeRecognizer.cs","lineNumber":125,"sourceCode":"        }\n\n        /// <summary>\n        /// Recognize the strokes.\n        /// </summary>\n        /// <param name=\"strokes\"></param>\n        /// <returns></returns>\n        internal GestureRecognitionResult[] Recognize(StrokeCollection strokes)\n        {\n            ObjectDisposedException.ThrowIf(_disposed, typeof(NativeRecognizer));\n\n            //\n            // note that we validate this argument from GestureRecognizer \n            // but since this is marked TAS, we want to do it here as well\n            //\n            ArgumentNullException.ThrowIfNull(strokes);\n            if (strokes.Count > 2)\n            {\n                throw new ArgumentException(SR.StrokeCollectionCountTooBig, nameof(strokes));\n            }\n\n            // Create an empty result.\n            GestureRecognitionResult[] recResults = Array.Empty<GestureRecognitionResult>();\n\n            if ( strokes.Count == 0 )\n            {\n                return recResults;\n            }\n\n            int hr = 0;\n\n            try\n            {\n                // Reset the context\n                hr = MS.Win32.Recognizer.UnsafeNativeMethods.ResetContext(_hContext);\n                if (HRESULT.Failed(hr))\n                {","sourceCodeStart":107,"sourceCodeEnd":143,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/PresentationCore/MS/internal/Ink/GestureRecognizer/NativeRecognizer.cs#L107-L143","documentation":"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.","triggerScenarios":"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.","commonSituations":"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').","solutions":["Split the StrokeCollection into chunks of at most 2 strokes and call Recognize per chunk","Pass only the stroke(s) from the gesture event (e.g. e.Strokes on InkCanvasGestureEventArgs)","Remove the extra strokes before calling Recognize","If more strokes must be analyzed, run recognition incrementally and merge results"],"exampleFix":"// before\nrecognizer.Recognize(inkCanvas.Strokes);\n// after\nforeach (var s in inkCanvas.Strokes) { var result = recognizer.Recognize(new StrokeCollection { s }); }","handlingStrategy":"validation","validationCode":"if (strokes == null) throw new ArgumentNullException(nameof(strokes));\nif (strokes.Count > 2) throw new ArgumentException(\"Recognize accepts at most 2 strokes\", nameof(strokes));","typeGuard":"static bool CanRecognize(StrokeCollection s) => s != null && s.Count >= 1 && s.Count <= 2;","tryCatchPattern":"try { return recognizer.Recognize(strokes); }\ncatch (ArgumentException) { return Array.Empty<GestureRecognitionResult>(); }","preventionTips":["Pass event-provided strokes (InkCanvasGestureEventArgs.Strokes), never the full canvas collection","Remember recognition is per 1-2 strokes; chunk larger sets","Add an assertion in debug builds for stroke count"],"tags":["wpf","ink","argument-validation","gesture-recognition"],"backgroundTag":"invalid-argument-value","analyzedSha":"81131a70a4c573cd62748a5c36908fc4d662daa9","analyzedAt":"2026-09-14T10:12:48.479Z","contentChangedAt":"2026-09-14T10:12:48.479Z","schemaVersion":2},"datasetVersion":"2026-09-21T21:30:21.729Z"}