Bokeh 2.3.0 Websocket Closed & Reopens when updating plot

Hi Guys,

I’m currently having issues with bokeh 2.3.0 I wasn’t having with the previous version, I’m getting:
2021-03-11 10:10:59,483 WebSocket connection closed: code=1001, reason=None
2021-03-11 10:11:00,139 WebSocket connection opened

when I try to update a plot in my bokeh --serve app, this seems to happen at random and not with every update, when I go to developer tools in chrome I see this:

The warning happens since the beginning, maybe due to the fact that the plot is empty at first, but the Error in red shows when I get the Web socket connection print in my console, this has never happened to me before with previous bokeh releases.

Hopefully someone can point me in the right direction.

Thanks

@David_Avila I can’t reproduce any issues with the examples from the repo so to investigate this we would need more info (platform, environment details) and most especially a Minimal Reproducible Example.

The only place I can find in the codebase with that message is in the BitSet data structure, which is used by CDS filters:

bokeh/bitset.ts at branch-2.4 · bokeh/bokeh · GitHub

So potentially an issue (usage or bug, investigation is necessary) with filters.

cc @mateusz

@Bryan I add an example, this one also fails in 2.3.0, it doesn’t in 2.2.3, the column length of the column data source changes when you choose a different number in the MultiSelect, the plot also updates when the MultiSelect value changes

from bokeh.models.widgets import MultiSelect
from bokeh.layouts import layout
from bokeh.plotting import figure, curdoc
from bokeh.models import ColumnDataSource, HoverTool
import numpy as np
import pandas as pd

#Column Data Sources
source_data = ColumnDataSource(
    data=dict(X=[], Y=[], main_legend=[], color=[], marker=[], alpha=[])
)

def update(attr, old, new):
    if plot_multi_select.value:
        val = int(plot_multi_select.value[0])
    else:
        val = 1
    x = np.linspace(0,val,val*10)
    y  = np.zeros_like(x)
    y = x**val
    df = pd.DataFrame()
    df["X"] = x
    df["Y"] = y
    df["color"] = "blue"
    df["alpha"] = 0.7
    df["marker"] = "circle"
    df["main_legend"] = str(val)
    source_data.data.update(ColumnDataSource(data=df).data)

#Multiselect
plot_multi_select = MultiSelect(
    title="Plot Select:",
    value=["2"],
    options=["2","3","4"],
    height=200
)
plot_multi_select.on_change("value", update)
#main plot
plot = figure(
    plot_width=1270,
    plot_height=900,
    tools="pan,wheel_zoom,box_zoom,reset,save",
    toolbar_location="left",
    output_backend="canvas",
)
# Plot scatter artist
sc = plot.scatter(
    x="X",
    y="Y",
    source=source_data,
    legend_field="main_legend",
    size=10,
    color="color",
    marker="marker",
    alpha='alpha',
)

TOOLTIPS = [
    ("(x,y)", "(@X,@Y)"),
    ("COLOR","$color[swatch]:color"),
]
hover = HoverTool(tooltips=TOOLTIPS, renderers=[sc])

plot.renderers.extend([sc])
plot.add_tools(hover)
plot.toolbar.logo = None
#legend
plot.add_layout(plot.legend[0], "right")
plot.legend.click_policy = "hide"
plot.legend.label_text_font_size = "8pt"
#grid
plot.grid.minor_grid_line_color = "#f2f2f2"
plot.grid.minor_grid_line_dash = "dashed"
#axis
plot.xaxis.axis_label = "X"
plot.yaxis.axis_label = "Y"
plot.xaxis.axis_label_text_font_size = "14pt"
plot.yaxis.axis_label_text_font_size = "14pt"

l = layout(children=[[plot,plot_multi_select]])

curdoc().add_root(l)
curdoc().title = "MINIMAL EXAMPLE"
curdoc().theme = 'light_minimal'

@David_Avila This seems like a bug (specifically, when the data size shrinks). Can you strip out all the extraneous unrelated bits (styling, tools, etc) and make a GitHub Issue?

@Bryan Sure thing, thanks for your support.

1 Like

@Bryan just to let you know, the problem is exactly in, if you comment the following line the problem disappears

plot.renderers.extend([sc])

it also only seems to happen when the columnDataSource reduces in length relative to the last update, as long as it keeps increasing in length in each update there is no issue, that’s all I could find, I’ll add it to the GitHub issue, thanks again

1 Like

@David_Avila I actually missed that line. plot.scatter already adds the renderer, it is not necessary to extend plot.renderers yourself. That’s only an issue if you use the lowest level bokeh.models API directly.

@David_Avila I finally had a chance to try it out without that line and I see it works as expected. Pleas feel free to still make an issue. It’s possible there is a sensible way to make double-adding renderers not be a problem, but if nothing else we could ad a validation check to warn when a renderer has been double-added.