dotnet/wpf · error · InvalidOperationException

throw new…

Error message

throw new InvalidOperationException(SR.HwndSubclassMultipleAttach);

What it means

HwndSubclass.Attach can only be called once per HwndSubclass instance. If the instance is already attached to a window (or detach is pending), calling Attach again throws InvalidOperationException (HwndSubclassMultipleAttach) because one instance may only bond to one HWND.

Solutions

  1. Create a new HwndWrapper/subclass instance for each new HWND instead of reattaching
  2. Check/track attachment state before calling Attach; only attach when the instance is unattached
  3. Ensure the previous detach (RequestDetach/Detach) completed before reusing the instance

Example fix

// before
if (_hwndSubclass == null) { /* reuse */ } _hwndSubclass.Attach(hwnd); // second attach throws
// after
_hwndSubclass = new HwndWrapper(...); // fresh instance per HWND
_hwndSubclass.Attach(hwnd);
Defensive patterns

Strategy: try-catch

Validate before calling

if (hwndSubclass.IsAttached) return; // track attach state yourself
hwndSubclass.Attach(hwnd);

Try / catch

try { hwndSubclass.Attach(hwnd); } catch (InvalidOperationException) { /* already attached: allocate a fresh instance */ }

Prevention

When it happens

Trigger: Calling Attach(hwnd) twice on the same HwndWrapper/subclass instance without the window having been destroyed/detached; reattaching after a failed detach; sharing one wrapper across two HWNDs.

Common situations: Re-creating a window handle (Handle recursed) and reusing the old wrapper object; double-initialization of a control; window recreation during theme change reattaching a cached subclass.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14). Data as JSON: /api/errors/d4a40661be64e85f. Report an issue: GitHub.

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/HwndSubclass.cs:120

        }

        /// <summary>
        ///     This method subclasses the specified window, such that the
        ///     delegate specified to the constructor will be called to process
        ///     the messages that are sent or posted to this window.
        /// </summary>
        /// <param name="hwnd">
        ///     The window to subclass.
        /// </param>
        /// <returns>
        ///     An identifier that can be used to reference this instance of
        ///     the HwndSubclass class in the static RequestDetach method.
        /// </returns>
        internal IntPtr Attach(IntPtr hwnd)
        {

            if (_bond != Bond.Unattached)
                throw new InvalidOperationException(SR.HwndSubclassMultipleAttach);

            return CriticalAttach( hwnd ) ;
        }


        /// <summary>
        ///     This method unsubclasses this HwndSubclass object from the window
        ///     it previously subclassed. The HwndSubclass object is not thread
        ///     safe, and should thus be called only by the thread that owns
        ///     the window being unsubclassed.
        /// </summary>
        /// <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>

View on GitHub (pinned to 81131a70a4)