Weird behavior when using template and browser inspect tool

I’m working on a complex application composed of several components. Each component can be a direct instance of param.Parameterized or pn.viewable.Viewer.

I’ve been able to create a simple example in order to show this weird behavior.

import panel as pn
import param
from bokeh.plotting import figure
from bokeh.models import ColumnDataSource
import numpy as np
pn.extension()

class Component(pn.viewable.Viewer):
    sel = param.Selector(default="r1", objects=["r1", "r2"])
    fig = param.ClassSelector(class_=figure)
    m = param.Number(default=1, bounds=(0, 2))
    
    def __init__(self, **params):
        super().__init__(**params)
        
        x = np.array([0, 1, 2, 3, 4])
        y1 = self.m * x
        y2 = -self.m * x

        self.fig = figure(height=250)
        r1 = self.fig.line(x, y1, line_color="red")
        r2 = self.fig.line(x, y2, line_color="green")
        r2.visible = False

    @param.depends("sel", watch=True)
    def _update_renderer_visibility(self):
        idx = self.param.sel.objects.index(self.sel)
        for i, r in enumerate(self.fig.renderers):
            r.visible = i == idx

    @param.depends("m", watch=True)
    def _update_data(self):
        x = self.fig.renderers[0].data_source.data["x"]
        self.fig.renderers[0].data_source.data.update({
            "y": self.m * x
        })
        self.fig.renderers[1].data_source.data.update({
            "y": -self.m * x
        })

    def __panel__(self):
        return pn.Column(
            self.param.sel,
            self.param.m,
            self.fig,
        )


template = pn.template.MaterialTemplate(
    # main=Component()
    main=pn.Column(Component())
)

template.show()

Note that when I created the template I used main=pn.Column(Component()). This is because my application shows several components in a single column.

It seems like that this pn.Column, causes the application to raise an error on the server side after I open the browser inspect tool, after which the application doesn’t work anymore: RuntimeError: _pending_writes should be non-None when we have a document lock, and we should have the lock when the document changes.

Am I doing something wrong? Is this some kind of bug?

2025-04-29 13:43:31,009 ERROR: panel.reactive - Callback failed for object named 'Sel' changing property {'value': 'r2'} 
Traceback (most recent call last):
  File "/.venv/lib/python3.12/site-packages/panel/reactive.py", line 464, in _process_events
    self.param.update(**self_params)
  File "/.venv/lib/python3.12/site-packages/param/parameterized.py", line 2406, in update
    restore = dict(self_._update(arg, **kwargs))
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/.venv/lib/python3.12/site-packages/param/parameterized.py", line 2439, in _update
    self_._batch_call_watchers()
  File "/.venv/lib/python3.12/site-packages/param/parameterized.py", line 2624, in _batch_call_watchers
    self_._execute_watcher(watcher, events)
  File "/.venv/lib/python3.12/site-packages/param/parameterized.py", line 2586, in _execute_watcher
    watcher.fn(*args, **kwargs)
  File "/.venv/lib/python3.12/site-packages/panel/param.py", line 535, in link_widget
    self.object.param.update(**{p_name: change.new})
  File "/.venv/lib/python3.12/site-packages/param/parameterized.py", line 2406, in update
    restore = dict(self_._update(arg, **kwargs))
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/.venv/lib/python3.12/site-packages/param/parameterized.py", line 2439, in _update
    self_._batch_call_watchers()
  File "/.venv/lib/python3.12/site-packages/param/parameterized.py", line 2624, in _batch_call_watchers
    self_._execute_watcher(watcher, events)
  File "/.venv/lib/python3.12/site-packages/param/parameterized.py", line 2586, in _execute_watcher
    watcher.fn(*args, **kwargs)
  File "/.venv/lib/python3.12/site-packages/param/parameterized.py", line 767, in _sync_caller
    return function()
           ^^^^^^^^^^
  File "/.venv/lib/python3.12/site-packages/param/depends.py", line 85, in _depends
    return func(*args, **kw)
           ^^^^^^^^^^^^^^^^^
  File "/tmp/ipykernel_154213/1413694909.py", line 29, in _update_renderer_visibility
    r.visible = i == idx
    ^^^^^^^^^
  File "/.venv/lib/python3.12/site-packages/bokeh/core/has_props.py", line 336, in __setattr__
    return super().__setattr__(name, value)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/.venv/lib/python3.12/site-packages/bokeh/core/property/descriptors.py", line 332, in __set__
    self._set(obj, old, value, setter=setter)
  File "/.venv/lib/python3.12/site-packages/bokeh/core/property/descriptors.py", line 614, in _set
    self._trigger(obj, old, value, hint=hint, setter=setter)
  File "/.venv/lib/python3.12/site-packages/bokeh/core/property/descriptors.py", line 692, in _trigger
    obj.trigger(self.name, old, value, hint, setter)
  File "/.venv/lib/python3.12/site-packages/bokeh/model/model.py", line 583, in trigger
    super().trigger(descriptor.name, old, new, hint=hint, setter=setter)
  File "/.venv/lib/python3.12/site-packages/bokeh/util/callback_manager.py", line 177, in trigger
    self.document.callbacks.notify_change(cast(Model, self), attr, old, new, hint, setter, invoke)
  File "/.venv/lib/python3.12/site-packages/bokeh/document/callbacks.py", line 251, in notify_change
    self.trigger_on_change(event)
  File "/.venv/lib/python3.12/site-packages/bokeh/document/callbacks.py", line 423, in trigger_on_change
    invoke_with_curdoc(doc, invoke_callbacks)
  File "/.venv/lib/python3.12/site-packages/bokeh/document/callbacks.py", line 453, in invoke_with_curdoc
    return f()
           ^^^
  File "/.venv/lib/python3.12/site-packages/bokeh/document/callbacks.py", line 422, in invoke_callbacks
    cb(event)
  File "/.venv/lib/python3.12/site-packages/bokeh/document/callbacks.py", line 278, in <lambda>
    self._change_callbacks[receiver] = lambda event: event.dispatch(receiver)
                                                     ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/.venv/lib/python3.12/site-packages/bokeh/document/events.py", line 352, in dispatch
    super().dispatch(receiver)
  File "/.venv/lib/python3.12/site-packages/bokeh/document/events.py", line 218, in dispatch
    cast(DocumentPatchedMixin, receiver)._document_patched(self)
  File "/.venv/lib/python3.12/site-packages/bokeh/server/session.py", line 244, in _document_patched
    raise RuntimeError("_pending_writes should be non-None when we have a document lock, and we should have the lock when the document changes")
RuntimeError: _pending_writes should be non-None when we have a document lock, and we should have the lock when the document changes

main should be a list. Try changing to

main=[pn.Column(Component())]

No, it doesn’t appear to help. I believe it automatically converts it to a list.

This behavior appears to be caused by launching the application in a new browser window from the notebook. If I serve the application with panel serve everything works as excepted.

I consider this problem solved.