Multiple errors in threaded apps with Panel 1.10.0

When migrating a threaded app to Panel 1.10.0 with pn.ui components, I’m seeing errors I was not seeing before when loading components and updating DynamicMaps.

First, I have issues where a plot does not respond to a widget update after being loaded, and I see the following:

2026-10-29 16:18:44,132 error handling message
 message: Message 'PATCH-DOC' content: {'events': [{'kind': 'ModelChanged', 'model': {'id': 'p1607096'}, 'attr': 'value_throttled', 'new': 10}]}
 error: UnknownReferenceError("can't resolve reference 'p1607096'")
Traceback (most recent call last):
  File "/home/user/workspace/.venv/lib/python3.12/site-packages/bokeh/server/protocol_handler.py", line 94, in handle
    work = await handler(message, connection)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/user/workspace/.venv/lib/python3.12/site-packages/bokeh/server/session.py", line 153, in _needs_document_lock_wrapper
    raise error
  File "/home/user/workspace/.venv/lib/python3.12/site-packages/bokeh/server/session.py", line 138, in _needs_document_lock_wrapper
    result = await result
             ^^^^^^^^^^^^
  File "/home/user/workspace/.venv/lib/python3.12/site-packages/bokeh/server/session.py", line 380, in _handle_patch
    await _run_in_executor(message.apply_to_document, self.document, self)
  File "/home/user/workspace/.venv/lib/python3.12/site-packages/bokeh/util/asyncio.py", line 104, in _run_in_executor
    return await _wait_for_task(worker)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/user/workspace/.venv/lib/python3.12/site-packages/bokeh/util/asyncio.py", line 78, in _wait_for_task
    result = await asyncio.shield(task)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/asyncio/threads.py", line 25, in to_thread
    return await loop.run_in_executor(None, func_call)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/concurrent/futures/thread.py", line 58, in run
    result = self.fn(*self.args, **self.kwargs)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/user/workspace/.venv/lib/python3.12/site-packages/bokeh/protocol/messages/patch_doc.py", line 102, in apply_to_document
    invoke_with_curdoc(doc, lambda: doc.apply_json_patch(self.payload, setter=setter))
  File "/home/user/workspace/.venv/lib/python3.12/site-packages/bokeh/document/callbacks.py", line 468, in invoke_with_curdoc
    return f()
           ^^^
  File "/home/user/workspace/.venv/lib/python3.12/site-packages/bokeh/protocol/messages/patch_doc.py", line 102, in <lambda>
    invoke_with_curdoc(doc, lambda: doc.apply_json_patch(self.payload, setter=setter))
                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/user/workspace/.venv/lib/python3.12/site-packages/panel/io/document.py", line 325, in _apply_json_patch
    return apply_json_patch(doc, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/user/workspace/.venv/lib/python3.12/site-packages/bokeh/document/document.py", line 463, in apply_json_patch
    patch: PatchJson = deserializer.deserialize(patch_json)
                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/user/workspace/.venv/lib/python3.12/site-packages/bokeh/core/serialization.py", line 523, in deserialize
    return self.decode(obj.content, obj.buffers)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/user/workspace/.venv/lib/python3.12/site-packages/bokeh/core/serialization.py", line 538, in decode
    return self._decode(obj)
           ^^^^^^^^^^^^^^^^^
  File "/home/user/workspace/.venv/lib/python3.12/site-packages/bokeh/core/serialization.py", line 579, in _decode
    return {key: self._decode(val) for key, val in obj.items()}
                 ^^^^^^^^^^^^^^^^^
  File "/home/user/workspace/.venv/lib/python3.12/site-packages/bokeh/core/serialization.py", line 581, in _decode
    return [self._decode(entry) for entry in obj]
            ^^^^^^^^^^^^^^^^^^^
  File "/home/user/workspace/.venv/lib/python3.12/site-packages/bokeh/core/serialization.py", line 579, in _decode
    return {key: self._decode(val) for key, val in obj.items()}
                 ^^^^^^^^^^^^^^^^^
  File "/home/user/workspace/.venv/lib/python3.12/site-packages/bokeh/core/serialization.py", line 577, in _decode
    return self._decode_ref(cast(Ref, obj))
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/user/workspace/.venv/lib/python3.12/site-packages/bokeh/core/serialization.py", line 591, in _decode_ref
    self.error(UnknownReferenceError(id))
  File "/home/user/workspace/.venv/lib/python3.12/site-packages/bokeh/core/serialization.py", line 744, in error
    raise error
bokeh.core.serialization.UnknownReferenceError: can't resolve reference 'p1607096'

I also encounter quite a lot of the following error, when updating a DynamicMap plot:

2026-10-29 16:09:27,567 ERROR:
Traceback (most recent call last):
  File "/home/user/workspace/.venv/lib/python3.12/site-packages/holoviews/plotting/bokeh/util.py", line 960, in wrapper
    return f(self, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/user/workspace/.venv/lib/python3.12/site-packages/holoviews/plotting/bokeh/element.py", line 2711, in update_frame
    self._update_ranges(style_element, ranges)
  File "/home/user/workspace/.venv/lib/python3.12/site-packages/holoviews/plotting/bokeh/element.py", line 1606, in _update_ranges
    self._update_main_ranges(element, x_range, y_range, ranges)
  File "/home/user/workspace/.venv/lib/python3.12/site-packages/holoviews/plotting/bokeh/element.py", line 1827, in _update_main_ranges
    self._update_range(
  File "/home/user/workspace/.venv/lib/python3.12/site-packages/holoviews/plotting/bokeh/element.py", line 1902, in _update_range
    axis_range.update(**{k: new})
  File "/home/user/workspace/.venv/lib/python3.12/site-packages/bokeh/core/has_props.py", line 538, in update
    setattr(self, k, v)
  File "/home/user/workspace/.venv/lib/python3.12/site-packages/bokeh/core/has_props.py", line 392, in __setattr__
    return super().__setattr__(name, value)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/user/workspace/.venv/lib/python3.12/site-packages/bokeh/core/property/descriptors.py", line 361, in __set__
    self._set(obj, old, value, setter=setter)
  File "/home/user/workspace/.venv/lib/python3.12/site-packages/bokeh/core/property/descriptors.py", line 645, in _set
    self._trigger(obj, old, value, hint=hint, setter=setter)
  File "/home/user/workspace/.venv/lib/python3.12/site-packages/bokeh/core/property/descriptors.py", line 723, in _trigger
    cast(_HasTrigger, obj).trigger(self.name, old, value, hint, setter)
  File "/home/user/workspace/.venv/lib/python3.12/site-packages/bokeh/model/model.py", line 593, in trigger
    super().trigger(descriptor.name, old, new, hint=hint, setter=setter)
  File "/home/user/workspace/.venv/lib/python3.12/site-packages/bokeh/util/callback_manager.py", line 181, in trigger
    self.document.callbacks.notify_change(cast(Model, self), attr, old, new, hint, setter, invoke)
  File "/home/user/workspace/.venv/lib/python3.12/site-packages/bokeh/document/callbacks.py", line 266, in notify_change
    self.trigger_on_change(event)
  File "/home/user/workspace/.venv/lib/python3.12/site-packages/bokeh/document/callbacks.py", line 438, in trigger_on_change
    invoke_with_curdoc(doc, invoke_callbacks)
  File "/home/user/workspace/.venv/lib/python3.12/site-packages/bokeh/document/callbacks.py", line 468, in invoke_with_curdoc
    return f()
           ^^^
  File "/home/user/workspace/.venv/lib/python3.12/site-packages/bokeh/document/callbacks.py", line 437, in invoke_callbacks
    cb(event)
  File "/home/user/workspace/.venv/lib/python3.12/site-packages/bokeh/document/callbacks.py", line 293, in <lambda>
    self._change_callbacks[receiver] = lambda event: event.dispatch(receiver)
                                                     ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/user/workspace/.venv/lib/python3.12/site-packages/bokeh/document/events.py", line 397, in dispatch
    super().dispatch(receiver)
  File "/home/user/workspace/.venv/lib/python3.12/site-packages/bokeh/document/events.py", line 252, in dispatch
    receiver._document_patched(self)
  File "/home/user/workspace/.venv/lib/python3.12/site-packages/bokeh/server/session.py", line 313, 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

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/lib/python3.12/concurrent/futures/thread.py", line 58, in run
    result = self.fn(*self.args, **self.kwargs)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/user/workspace/.venv/lib/python3.12/site-packages/panel/reactive.py", line 567, in _change_event
    self._process_events(events)
  File "/home/user/workspace/.venv/lib/python3.12/site-packages/panel/widgets/slider.py", line 112, in _process_events
    super()._process_events(events)
  File "/home/user/workspace/.venv/lib/python3.12/site-packages/panel/reactive.py", line 510, in _process_events
    raise e
  File "/home/user/workspace/.venv/lib/python3.12/site-packages/panel/reactive.py", line 491, in _process_events
    self.param.update(**self_params)
  File "/home/user/workspace/.venv/lib/python3.12/site-packages/param/parameterized.py", line 3164, in update
    restore = {**(self_._update(arg, **kwargs))}
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/user/workspace/.venv/lib/python3.12/site-packages/param/parameterized.py", line 3205, in _update
    self_._batch_call_watchers()
  File "/home/user/workspace/.venv/lib/python3.12/site-packages/param/parameterized.py", line 3455, in _batch_call_watchers
    self_._execute_watcher(watcher, events)
  File "/home/user/workspace/.venv/lib/python3.12/site-packages/param/parameterized.py", line 3417, in _execute_watcher
    watcher.fn(*args, **kwargs)
  File "/home/user/workspace/.venv/lib/python3.12/site-packages/panel/pane/holoviews.py", line 409, in _widget_callback
    self._update_plot(plot, pane)
  File "/home/user/workspace/.venv/lib/python3.12/site-packages/panel/pane/holoviews.py", line 394, in _update_plot
    plot.update(key)
  File "/home/user/workspace/.venv/lib/python3.12/site-packages/holoviews/plotting/plot.py", line 1087, in update
    item = self.__getitem__(key)
           ^^^^^^^^^^^^^^^^^^^^^
  File "/home/user/workspace/.venv/lib/python3.12/site-packages/holoviews/plotting/plot.py", line 506, in __getitem__
    self.update_frame(frame)
  File "/home/user/workspace/.venv/lib/python3.12/site-packages/holoviews/plotting/bokeh/util.py", line 962, in wrapper
    self.state.hold_render = hold
    ^^^^^^^^^^^^^^^^^^^^^^
  File "/home/user/workspace/.venv/lib/python3.12/site-packages/bokeh/models/plots.py", line 131, in __setattr__
    super().__setattr__(name, value)
  File "/home/user/workspace/.venv/lib/python3.12/site-packages/bokeh/core/has_props.py", line 392, in __setattr__
    return super().__setattr__(name, value)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/user/workspace/.venv/lib/python3.12/site-packages/bokeh/core/property/descriptors.py", line 361, in __set__
    self._set(obj, old, value, setter=setter)
  File "/home/user/workspace/.venv/lib/python3.12/site-packages/bokeh/core/property/descriptors.py", line 645, in _set
    self._trigger(obj, old, value, hint=hint, setter=setter)
  File "/home/user/workspace/.venv/lib/python3.12/site-packages/bokeh/core/property/descriptors.py", line 723, in _trigger
    cast(_HasTrigger, obj).trigger(self.name, old, value, hint, setter)
  File "/home/user/workspace/.venv/lib/python3.12/site-packages/bokeh/model/model.py", line 593, in trigger
    super().trigger(descriptor.name, old, new, hint=hint, setter=setter)
  File "/home/user/workspace/.venv/lib/python3.12/site-packages/bokeh/util/callback_manager.py", line 181, in trigger
    self.document.callbacks.notify_change(cast(Model, self), attr, old, new, hint, setter, invoke)
  File "/home/user/workspace/.venv/lib/python3.12/site-packages/bokeh/document/callbacks.py", line 266, in notify_change
    self.trigger_on_change(event)
  File "/home/user/workspace/.venv/lib/python3.12/site-packages/bokeh/document/callbacks.py", line 438, in trigger_on_change
    invoke_with_curdoc(doc, invoke_callbacks)
  File "/home/user/workspace/.venv/lib/python3.12/site-packages/bokeh/document/callbacks.py", line 468, in invoke_with_curdoc
    return f()
           ^^^
  File "/home/user/workspace/.venv/lib/python3.12/site-packages/bokeh/document/callbacks.py", line 437, in invoke_callbacks
    cb(event)
  File "/home/user/workspace/.venv/lib/python3.12/site-packages/bokeh/document/callbacks.py", line 293, in <lambda>
    self._change_callbacks[receiver] = lambda event: event.dispatch(receiver)
                                                     ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/user/workspace/.venv/lib/python3.12/site-packages/bokeh/document/events.py", line 397, in dispatch
    super().dispatch(receiver)
  File "/home/user/workspace/.venv/lib/python3.12/site-packages/bokeh/document/events.py", line 252, in dispatch
    receiver._document_patched(self)
  File "/home/user/workspace/.venv/lib/python3.12/site-packages/bokeh/server/session.py", line 313, 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

These do not seem to occur in a non-threaded app.

I’m still working out a way to build minimal reproducible examples so that I can create issues on GitHub. In the meantime, are there specific patterns to avoid or things to look out for when dynamically updating content in a threaded app?

I’m on bokeh 3.10.1

Thanks for reporting. How are you creating those DynamicMaps?

Thank you @ahuang11 for your reply.

Things happen in the main area of a pn.ui.Page. The app is config-driven, with a fairly generic code to build the DynamicMap:

dmap = hv.DynamicMap(
                functools.partial(
                    self._make_dmap_plot,
                    df=df,
                    kdims=kdims,
                    vdims=vdims,
                    plot_cfg=plot_cfg,
                    label=label,
                ),
                kdims=interactive_dims,
            )
            dmap = dmap.redim.values(
                **{dim.name: df[dim.name].unique().tolist() for dim in interactive_dims}
            )

self._make_dmap_plot itself is a static method:

    @staticmethod
    def _make_dmap_plot(
        *selected_values, df=None, kdims=None, vdims=None, plot_cfg=None, label=None
    ):
        dframe = df.loc[
            (
                df[[dim.id for dim in plot_cfg.interactive_dims]]
                == list(selected_values)
            ).all(axis=1)
        ]
        return ELEMENT_TYPE[plot_cfg.type](
            dframe, kdims=kdims, vdims=vdims, group=plot_cfg.id, label=label
        ).opts(framewise=True)

where ELEMENT_TYPE is a global dictionary holding hv element types.

The DynamicMap is then wrapped in a hv.Overlay (even if it’s alone), which is then collated (overlay = overlay.collate()) and then with pn.panel this way:

            obj = pn.panel(
                overlay,
                widgets=widgets,
                widget_layout=pn.Row,
                widget_location="top",
            )

where widgets is a kdim -> widget_class mapping (pn.ui.Select or pn.ui.DiscreteSlider in this case).

The collection of plots are then passed to pn.viewable.Viewer object that updates its content to include the dmap(s).

Two things that stand out to me:

  1. functools.partial
  2. collate

Does the issue still appear with these two excluded

Thanks @ahuang11, I finally tracked it down to simply using the Page template. Filing another issue on github!