CometD Issues when subscribing to Platform Events

This is a know issue documented in the Platform Event project Build an Instant Notification App:

If you notice an "Exception during handling of messages Unrecognized advice action handshake" error in your developer console, please turn off notifications for your org:

  1. From Setup, enter Notifications in the Quick Find box, then select Salesforce Notifications.
  2. Uncheck the Enable in-app notifications and Enable push notifications checkboxes.
  3. Click Save.
  4. Log out then log in again.

This happens because of a conflict between the CometD connection that your app is trying to establish and the connection used internally by Salesforce to track notifications.

EDIT on Nov 13 2018: this issue is now solved with the use of lightning:empApi and the Trailhead project has been update accordingly.
Read more about this component in this blog post


I'm receiving this message as well. Not in the Trailhead but in my own code both within Visualforce page and withing a lightning component. I don't think you can catch this exception as it's caught by the cometd.js client lib. Note... before that happens.... in a connect listener I am seeing at 403::Unknown Client message.. then the cometd tries to handshaked / subscribe again (which it should).. then the unrecognized handshake message is caught by cometd.js.

Note. 403::Unknown client is not a standard error thrown by the cometd server code. this is probably a sfdc customized version of server code (@see https://github.com/cometd/cometd/issues/644)

It's also possibly related to the version of the cometd client lib being used. I've seen different versions all over the place in different samples / demos..

There are many intricacies described by salesforce with long polling and what the 'client' should do after certain time periods. but the confusing point is what exactly is meant by the client. ie cometd.js or our code that uses cometd.js. none of the examples / samples have this type of beef to them.

refer to this issue. I may try later versions and let you know! https://github.com/cometd/cometd/issues/722

Durable streaming is not something I want to have to use for this as I don't want to send a replyfrom of -2 and get a ton of messages back for the last 24 hours (it's 24 hours or none basically)

Note. One thing I've done to defend against this which seems to work.. And I don't think it's right but it's the only way I have got it to work. is.. from a connect listener i'm looking for a 403.. if I get it.. I know I'm done. i basically unsubscribe / destroy. configure again. handshake and subscribe again. Feels like way too much but I'm not losing messages this way soo. until I can find a sample that shows me a better way. I'm sticking with it.

    /**
 * A meta/connect listener for cometd. generally cometd should rehandshake on it's own but in case we have issues
 * this may be the spot to address.
 *
 * @param component
 * @param event
 * @param helper
 */
addConnectListener: function(component, event, helper) {
    //--- extra meta/connect listener for further bulletproofing.... this makes me sad that we have to do this!!
    var cometd = component.get("v.cometd");
    cometd.addListener('/meta/connect',$A.getCallback(function(message) {
        if(!message.successful) {
            helper.log('--- streamer meta/connect..xxx isDisconnected?' + cometd.isDisconnected() + '... message.error..'+message.error + 'advice=' + JSON.stringify(message.advice) + '..  message='+JSON.stringify(message),'warn',message);
            var advice = message.advice;

            //if(reconnect && reconnect!==undefined && reconnect != null) {
            if(message.error.includes('403')) {
                helper.log('--- streamer.. cometd will attempt to rehandshake on its own according to spec but always fails after the next handshake !! im forcing an entire reinit of the component doing a handledestroy here doesnot seem necessary as unsubscribe always fails.', 'warn');
                helper.doReInit(component, event, helper);
            }
                //------------------------helper.handshake(component,event.helper);
            //}
        }
    }));
},

Full code

addConnectListener: function(component, event, helper) {
    //--- extra meta/connect listener for further bulletproofing.... this makes me sad that we have to do this!!
    var cometd = component.get("v.cometd");
    cometd.addListener('/meta/connect', $A.getCallback(function(message) {
        if(!message.successful) {
            //helper.log('--- streamer meta/connect..xxx isDisconnected?' + cometd.isDisconnected() + '... message.error..'+message.error + 'advice=' + JSON.stringify(message.advice) + '..  message='+JSON.stringify(message),'warn',message);
            var advice = message.advice;

            //if(reconnect && reconnect!==undefined && reconnect != null) {
            if(message.error.includes('403')) {
                //helper.log('--- streamer.. cometd will attempt to rehandshake on its own according to spec but always fails after the next handshake !! im forcing an entire reinit of the component doing a handledestroy here doesnot seem necessary as unsubscribe always fails.', 'warn');
                //helper.connectCometd(component, event, helper);
                //helper.getRecord(component);
                var cometd = component.get("v.cometd");
                // Unsuscribe all CometD subscriptions
                cometd.batch(function() {
                  var subscriptions = component.get('v.cometdSubscriptions');
                  subscriptions.forEach(function (subscription) {
                    cometd.unsubscribe(subscription);
                  });
                });
                component.set('v.cometdSubscriptions', []);

                cometd.disconnect();
                var cometd = new org.cometd.CometD();
                component.set('v.cometd', cometd);
                helper.connectCometd(component);
                helper.addConnectListener( component, event, helper);
            }
        }
    }));
},

connectCometd : function(component) {
    var helper = this;

    // Configure CometD
    var cometdUrl = window.location.protocol+'//'+window.location.hostname+'/cometd/42.0/';
    var cometd = component.get('v.cometd');
    cometd.configure({
        url: cometdUrl,
        requestHeaders: { Authorization: 'OAuth '+ component.get('v.sessionId')},
        appendMessageTypeToURL : false
    });
    cometd.websocketEnabled = false;

    // Establish CometD connection
    console.log('Connecting to CometD: '+ cometdUrl);
    cometd.handshake(function(handshakeReply) {


        if (handshakeReply.successful) {
            console.log('Connected to CometD.');
            // Subscribe to platform event
            var newSubscription = cometd.subscribe('/event/Platform_Event__e',
                $A.getCallback(function(platformEvent) {
                    console.log('Platform event received: '+ JSON.stringify(platformEvent));
                    //helper.getRecord(component);
                })
            );

            // Save subscription for later
            var subscriptions = component.get('v.cometdSubscriptions');
            subscriptions.push(newSubscription);
            component.set('v.cometdSubscriptions', subscriptions);
        }
        else
            console.error('Failed to connected to CometD.');
    });
},