# Buggy code
def open(self):
    """Initialize a connection to a client."""
    log.info("WebSocket connection opened")

    proto_version = self.get_argument("bokeh-protocol-version", default=None)
    if proto_version is None:
        self.close()
        raise ProtocolError("No bokeh-protocol-version specified")

    session_id = self.get_argument("bokeh-session-id", default=None)
    if session_id is None:
        self.close()
        raise ProtocolError("No bokeh-session-id specified")

    if not check_session_id_signature(
        session_id,
        signed=self.application.sign_sessions,
        secret_key=self.application.secret_key,
    ):
        log.error("Session id had invalid signature: %r", session_id)
        raise ProtocolError("Invalid session ID")

    def on_fully_opened(future):
        e = future.exception()
        if e is not None:
            # this isn't really an error (unless we have a
            # bug), it just means a client disconnected
            # immediately, most likely.
            log.debug("Failed to fully open connection %r", e)

    future = self._async_open(session_id, proto_version)
    self.application.io_loop.add_future(future, on_fully_opened)


# 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 open(self):
    """Initialize a connection to a client.

    Returns:
        None

    """
    log.info("WebSocket connection opened")

    proto_version = self.get_argument("bokeh-protocol-version", default=None)
    if proto_version is None:
        self.close()
        raise ProtocolError("No bokeh-protocol-version specified")

    session_id = self.get_argument("bokeh-session-id", default=None)
    if session_id is None:
        self.close()
        raise ProtocolError("No bokeh-session-id specified")

    if not check_session_id_signature(
        session_id,
        signed=self.application.sign_sessions,
        secret_key=self.application.secret_key,
    ):
        log.error("Session id had invalid signature: %r", session_id)
        raise ProtocolError("Invalid session ID")

    def on_fully_opened(future):
        e = future.exception()
        if e is not None:
            # this isn't really an error (unless we have a
            # bug), it just means a client disconnected
            # immediately, most likely.
            log.debug("Failed to fully open connection %r", e)

    future = self._async_open(session_id, proto_version)
    self.application.io_loop.add_future(future, on_fully_opened)