dotnet/wpf · error · InvalidOperationException

IConnectionPoint::Advise returned an invalid cookie.

Error message

IConnectionPoint::Advise returned an invalid cookie.

What it means

SafeConnectionPointCookie wraps a COM IConnectionPoint::Advise call that registers an event sink with a COM connection point and returns a cookie identifying the registration. This InvalidOperationException is thrown when Advise succeeds (does not throw) but returns a cookie of 0, which is not a valid registration handle. The library treats a zero cookie as evidence the COM object did not actually register the sink, so continuing would leave an unadviseable, corrupt connection.

Solutions

  1. Ensure the COM source object is fully initialized and alive before constructing SafeConnectionPointCookie.
  2. Verify the event GUID passed to the constructor matches a connection point the COM object genuinely supports (check FindConnectionPoint's returned cp is non-null).
  3. Wrap sink registration in try-catch for InvalidOperationException and fall back to polling or alternative event mechanisms for that COM object.
  4. If wrapping a third-party ActiveX control, test its Advise behavior; report or work around objects returning zero cookies.

Example fix

// before
var cookie = new SafeConnectionPointCookie(activeX.Document, this, typeof(DWebBrowserEvents2).GUID);
// after
if (activeX.Document == null) throw new InvalidOperationException("Document not ready");
try { var cookie = new SafeConnectionPointCookie(activeX.Document, this, typeof(DWebBrowserEvents2).GUID); }
catch (InvalidOperationException ex) { /* log: COM source did not register sink (cookie 0); use fallback */ }
Defensive patterns

Strategy: try-catch

Validate before calling

if (comTarget == null) throw new InvalidOperationException("COM target not ready");
// no pre-call API to probe cookie; guard by constructing inside try-catch

Try / catch

try {
    var cookie = new SafeConnectionPointCookie(target, sink, eventId);
} catch (InvalidOperationException ex) when (ex.Message.Contains("invalid cookie")) {
    log.Warn("COM Advise returned 0 cookie; sink not registered", ex);
    RegisterFallbackHandler();
}

Prevention

When it happens

Trigger: Calling SafeConnectionPointCookie's constructor with a COM target whose FindConnectionPoint succeeds for the given event IID but whose IConnectionPoint::Advise returns S_OK with dwCookie == 0 (e.g. a misbehaving or partially initialized COM source object).

Common situations: Hosting WPF WebBrowser/ActiveX controls (shDoccHost events, DWebBrowserEvents2) against non-standard or third-party COM objects that advertise connection points but fail to hand out real cookies; COM objects created before initialization completes or torn down concurrently.

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


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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Standard/NativeMethods.cs:1572

        [SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "IConnectionPoint")]
        public SafeConnectionPointCookie(IConnectionPointContainer target, object sink, Guid eventId)
            : base(true)
        {
            Verify.IsNotNull(target, "target");
            Verify.IsNotNull(sink, "sink");
            Verify.IsNotDefault(eventId, "eventId");

            handle = IntPtr.Zero;

            IConnectionPoint cp = null;
            try
            {
                int dwCookie;
                target.FindConnectionPoint(ref eventId, out cp);
                cp.Advise(sink, out dwCookie);
                if (dwCookie == 0)
                {
                    throw new InvalidOperationException("IConnectionPoint::Advise returned an invalid cookie.");
                }
                handle = new IntPtr(dwCookie);
                _cp = cp;
                cp = null;
            }
            finally
            {
                Utility.SafeRelease(ref cp);
            }
        }

        public void Disconnect()
        {
            ReleaseHandle();
        }

        [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]

View on GitHub (pinned to 81131a70a4)