dotnet/wpf · error · InvalidOperationException
InvalidOperationException
Error message
InvalidOperationException
What it means
WPF's stylus/touch (PenIMC) layer throws this bare InvalidOperationException from CheckedLockWispObjectFromGit when the native Win32 call LockWispObjectFromGit fails on Windows 8 or greater. Locking the WISP (Windows Ink Services Platform) Global Interface Table entry is a prerequisite for using the pen/ink subsystem; failure means the native tablet service did not grant the lock, so WPF aborts rather than continue with inconsistent state.
Solutions
- Ensure the Windows 'Tablet PC Input Service' (TabletInputService / TabSvc) is running on the machine.
- Check whether the app is running in an RDP/remote session; WISP real-time stylus is unavailable there - catch the exception or disable stylus-dependent features in remote sessions.
- Repair/verify Windows ink components (sfc /scannow, Windows Update, reinstall pen/display drivers).
- Wrap WPF window/ink initialization in try-catch and fall back to mouse-only input when WISP locking fails.
Example fix
// before (crash on RDP / no tablet service)
var win = new StylusWindow();
// after (degrade gracefully)
try
{
var win = new StylusWindow();
}
catch (InvalidOperationException)
{
// WISP GIT lock failed (no tablet service / RDP session)
EnableMouseOnlyMode();
} Defensive patterns
Strategy: try-catch
Validate before calling
// before creating WPF windows in constrained environments
bool stylusLikelyAvailable =
Environment.UserInteractive &&
!IsRemoteSession() &&
ServiceRunning("TabletInputService"); Try / catch
try
{
InitializeWpfWindow();
}
catch (InvalidOperationException ex) when (IsWispLockFailure(ex))
{
Log.Warn("WISP GIT lock failed; falling back to mouse-only input.");
EnableMouseOnlyMode();
} Prevention
- Verify TabletInputService (Tablet PC Input Service) is running before launching stylus-dependent features.
- Detect remote-desktop sessions and disable real-time stylus features there.
- Keep Windows and pen/digitizer drivers updated to keep WISP healthy.
- Add a global handler that degrades to mouse input instead of crashing when WISP initialization fails.
When it happens
Trigger: A WPF app that uses stylus/touch input (Tablet service, InkCanvas, real-time stylus) calls LockWispManager, which invokes CheckedLockWispObjectFromGit; the P/Invoke LockWispObjectFromGit returns false (native failure) on Windows 8+, causing the throw. Happens during TabletService/WispTabletDevice initialization.
Common situations: RDP/terminal-server or VM sessions where the tablet service is unavailable or disabled; Windows Tablet Input Service (TabletInputService/TabSvc) stopped or broken; systems where WISP components are corrupted or the pen driver stack fails; headless machines or sessions without a visible desktop that still touch the stylus code path.
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
- 0x80070057
- ArgumentNullException (buffer/sourceBuffer was IntPtr.Zero)
- Buffer address passed to GetText cannot be NULL.
- captureMode
- captureMode
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/ab217629e519e331.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/MS/Win32/UnsafeNativeMethodsPenimc.cs:181
return ((IPimcManager3)pimcManagerObj);
}
#region COM Locking/Unlocking Functions
#region General
/// <summary>
/// Calls WISP GIT lock functions on Win8+.
/// On Win7 these will always fail since WISP objects are always proxies (WISP is out of proc).
/// </summary>
/// <param name="gitKey">The GIT key for the object to lock.</param>
internal static void CheckedLockWispObjectFromGit(UInt32 gitKey)
{
if (OSVersionHelper.IsOsWindows8OrGreater)
{
if (!LockWispObjectFromGit(gitKey))
{
throw new InvalidOperationException();
}
}
}
/// <summary>
/// Calls WISP GIT unlock functions on Win8+.
/// On Win7 these will always fail since WISP objects are always proxies (WISP is out of proc).
/// </summary>
/// <param name="gitKey">The GIT key for the object to unlock.</param>
internal static void CheckedUnlockWispObjectFromGit(UInt32 gitKey)
{
if (OSVersionHelper.IsOsWindows8OrGreater)
{
if (!UnlockWispObjectFromGit(gitKey))
{
throw new InvalidOperationException();
}
}View on GitHub (pinned to 81131a70a4)