dotnet/wpf · error · ArgumentNullException
ArgumentNullException
Error message
ArgumentNullException
What it means
The second validation in HwndSubclass.RequestDetach: the 'subclass' parameter must be a non-zero IntPtr identifying the subclass instance. Passing IntPtr.Zero throws ArgumentNullException for subclass.
Solutions
- Pass the original non-zero subclass IntPtr (the gcHandle) used at attach time
- Guard with if (subclass != IntPtr.Zero) before calling RequestDetach
- Keep the subclass handle alive until detach completes; avoid clearing it during teardown
Example fix
// before HwndSubclass.RequestDetach(hwnd, IntPtr.Zero, true); // after if (_subclass != IntPtr.Zero) HwndSubclass.RequestDetach(hwnd, _subclass, true);
Defensive patterns
Strategy: validation
Validate before calling
if (hwnd == IntPtr.Zero || subclass == IntPtr.Zero) return; HwndSubclass.RequestDetach(hwnd, subclass, force);
Type guard
bool CanRequestDetach(IntPtr hwnd, IntPtr subclass) => hwnd != IntPtr.Zero && subclass != IntPtr.Zero;
Try / catch
try { HwndSubclass.RequestDetach(hwnd, subclass, force); } catch (ArgumentNullException ex) when (ex.ParamName == "subclass") { /* subclass reference lost; nothing to detach */ } Prevention
- Keep the subclass gcHandle IntPtr alive until detach completes
- Validate both handles before calling RequestDetach
- Clear subclass fields only after detach returns
When it happens
Trigger: Calling HwndSubclass.RequestDetach(hwnd, IntPtr.Zero, force) — a zero handle where the subclass (gcHandle wrapper) reference is required.
Common situations: The subclass reference field was never initialized or was cleared before detach; passing default(IntPtr) as a placeholder; race where detach runs after the wrapper reset its fields.
Related errors
- throw new ArgumentNullException(nameof(hwnd));
- throw new ArgumentNullException(nameof(callback));
- throw new ArgumentNullException(nameof(prefix));
- throw new…
- annotation component
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/6bddc1777047d20a.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/HwndSubclass.cs:227
/// <param name="force">
/// Whether or not the unsubclassing should be forced. Due to the
/// way that Win32 implements window subclassing, it is not always
/// possible to safely remove a window proc from the WNDPROC chain.
/// However, the delegate will not be called again after this
/// method returns.
/// </param>
/// <returns>
/// Nothing.
/// </returns>
internal static void RequestDetach(IntPtr hwnd, IntPtr subclass, bool force)
{
if(hwnd == IntPtr.Zero)
{
throw new ArgumentNullException(nameof(hwnd));
}
if(subclass == IntPtr.Zero)
{
throw new ArgumentNullException(nameof(subclass));
}
int iForce = force ? 1 : 0;
UnsafeNativeMethods.UnsafeSendMessage(hwnd, DetachMessage, subclass, (IntPtr) iForce);
}
/// <summary>
/// This is the WNDPROC that gets inserted into the window's
/// WNDPROC chain. It responds to various conditions that
/// would cause this HwndSubclass object to unsubclass the window,
/// and then calls the delegate specified to the HwndSubclass
/// constructor to process the message. If the delegate does not
/// handle the message, the message is then passed on down the
/// WNDPROC chain for further processing.
/// </summary>
/// <param name="hwnd">
/// The window that this message was sent or posted to.
/// </param>View on GitHub (pinned to 81131a70a4)