# Buggy code
def _async_open(self, session_id, proto_version):
    try:
        yield self.application_context.create_session_if_needed(
            session_id, self.request
        )
        session = self.application_context.get_session(session_id)

        protocol = Protocol(proto_version)
        self.receiver = Receiver(protocol)
        log.debug("Receiver created for %r", protocol)

        self.handler = ProtocolHandler()
        log.debug("ProtocolHandler created for %r", protocol)

        self.connection = self.application.new_connection(
            protocol, self, self.application_context, session
        )
        log.info("ServerConnection created")

    except ProtocolError as e:
        log.error("Could not create new server session, reason: %s", e)
        self.close()
        raise e

    msg = self.connection.protocol.create("ACK")
    yield self.send_message(msg)

    raise gen.Return(None)


# Traceback (tornado.iostream.StreamClosedError)
2018-03-12 09:05:56,504 200 GET /gapminder (::1) 134.13ms
2018-03-12 09:05:56,506 Sending pull-doc-reply from session 'c13X3Xet3szgUeNWFMzrL86pmFq77b8q04pGAUD8WUFJ'
2018-03-12 09:05:56,513 Failed sending message as connection was closed
2018-03-12 09:05:56,514 WebSocket connection closed: code=None, reason=None
2018-03-12 09:05:56,604 Future exception was never retrieved
future: <Future finished exception=WebSocketClosedError()>
Traceback (most recent call last):
File "/Users/bryanv/anaconda/envs/15dev1/lib/python3.6/site-packages/tornado/websocket.py", line 808, in wrapper
yield fut
File "/Users/bryanv/anaconda/envs/15dev1/lib/python3.6/site-packages/tornado/gen.py", line 1099, in run
value = future.result()
tornado.iostream.StreamClosedError: Stream is closed

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "/Users/bryanv/anaconda/envs/15dev1/lib/python3.6/site-packages/tornado/gen.py", line 1107, in run
yielded = self.gen.throw(*exc_info)
File "/Users/bryanv/anaconda/envs/15dev1/lib/python3.6/site-packages/tornado/websocket.py", line 810, in wrapper
raise WebSocketClosedError()
tornado.websocket.WebSocketClosedError

# Fixed code
def _async_open(self, session_id, proto_version):
    """Perform the specific steps needed to open a connection to a Bokeh session

    Sepcifically, this method coordinates:

    * Getting a session for a session ID (creating a new one if needed)
    * Creating a protocol receiver and hander
    * Opening a new ServerConnection and sending it an ACK

    Args:
        session_id (str) :
            A session ID to for a session to connect to

            If no session exists with the given ID, a new session is made

        proto_version (str):
            The protocol version requested by the connecting client.

    Returns:
        None

    """
    try:
        yield self.application_context.create_session_if_needed(
            session_id, self.request
        )
        session = self.application_context.get_session(session_id)

        protocol = Protocol(proto_version)
        self.receiver = Receiver(protocol)
        log.debug("Receiver created for %r", protocol)

        self.handler = ProtocolHandler()
        log.debug("ProtocolHandler created for %r", protocol)

        self.connection = self.application.new_connection(
            protocol, self, self.application_context, session
        )
        log.info("ServerConnection created")

    except ProtocolError as e:
        log.error("Could not create new server session, reason: %s", e)
        self.close()
        raise e

    msg = self.connection.protocol.create("ACK")
    yield self.send_message(msg)

    raise gen.Return(None)