dotnet/wpf · error · InvalidOperationException
Failed to set enabled gestures.
Error message
Failed to set enabled gestures.
What it means
Gesture recognition is performed through the native Tablet PC ink recognizer via a context handle (SetEnabledGestures P/Invoke). When the native call returns a failing HRESULT, the wrapper throws InvalidOperationException deliberately withholding COM error details because none are useful to surface. It means the native recognizer refused to update its enabled-gesture set.
Solutions
- Verify the Tablet PC / ink recognition components are installed and functional on the target machine
- Ensure the GestureRecognizer (and its native context) is still alive and not disposed when setting EnabledGestures
- Catch InvalidOperationException around the EnabledGestures assignment and degrade gracefully (disable gesture features)
- Re-create the GestureRecognizer instance to get a fresh native context and retry once
Example fix
// before
recognizer.EnabledGestures = new[] { ApplicationGesture.Down };
// after
try { recognizer.EnabledGestures = new[] { ApplicationGesture.Down }; }
catch (InvalidOperationException) { /* ink engine unavailable; fall back to no gesture recognition */ } Defensive patterns
Strategy: try-catch
Validate before calling
if (recognizer == null) throw new InvalidOperationException("Recognizer not initialized");
// ensure ink platform present before use
bool inkAvailable = OperatingSystem.IsWindows(); Type guard
static bool HasLiveContext(GestureRecognizer r) => r != null && !r.IsDisposed;
Try / catch
try { recognizer.EnabledGestures = gestures; }
catch (InvalidOperationException ex) { logger.LogWarning(ex, "Gesture enable failed"); gestureSupport = false; } Prevention
- Check ink-platform availability before enabling gesture features
- Keep the recognizer alive for the duration of use; avoid disposing mid-session
- Wrap all gesture configuration in a single guarded setup method
When it happens
Trigger: Calling GestureRecognizer.EnabledGestures setter (SetEnabledGestures) after the native recognizer context handle is invalid, disposed, or when the underlying ink recognition engine (Tablet PC platform / ISF components) is unavailable on the machine.
Common situations: Running on machines or in environments (e.g. non-Windows, server SKUs, containers) without the Tablet PC ink recognition service; using a GestureRecognizer whose native context has been disposed or failed to initialize.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- Gesture recognition failed.
- Failed to initialize GestureRecognizer.
- Maximum number of strokes is two.
- SR.GestureRecognizerNotAvailable
- SR.StrokeCollectionCountTooBig
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/4df70ae4acc2e95f.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/MS/internal/Ink/GestureRecognizer/NativeRecognizer.cs:103
/// <summary>
/// Set the enabled gestures
/// </summary>
/// <param name="applicationGestures"></param>
internal ApplicationGesture[] SetEnabledGestures(IEnumerable<ApplicationGesture> applicationGestures)
{
ObjectDisposedException.ThrowIf(_disposed, typeof(NativeRecognizer));
//validate and get an array out
ApplicationGesture[] enabledGestures =
GetApplicationGestureArrayAndVerify(applicationGestures);
// Set enabled Gestures.
int hr = SetEnabledGestures(_hContext, enabledGestures);
if (HRESULT.Failed(hr))
{
//don't throw a com exception here, we don't need to pass out any details
throw new InvalidOperationException(SR.UnspecifiedSetEnabledGesturesException);
}
return enabledGestures;
}
/// <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
//View on GitHub (pinned to 81131a70a4)