Skip to content

[BUG] 4.2.0rc1 websocket callback can't set_props() with Patch value #3758

@CNFeffery

Description

@CNFeffery

In version 4.2.0rc1, websocket-type callback functions cannot update Patch-type property values via set_props(), which prevents key scenarios such as streaming content updates in LLM applications from leveraging new features. Below is an example to reproduce the issue:

Image
import dash
from dash import html, set_props, Patch
from dash.dependencies import Input

app = dash.Dash(__name__, backend="fastapi")

app.layout = html.Div(
    [
        html.Div(
            [
                html.Button("normal set_props()", id="normal-set-props"),
                html.Div("initial value", id="normal-set-props-result"),
            ],
            style={"border": "1px solid #ccc", "padding": 10, "marginBottom": 10},
        ),
        html.Div(
            [
                html.Button("websocket set_props()", id="websocket-set-props"),
                html.Div("initial value", id="websocket-set-props-result"),
            ],
            style={"border": "1px solid #ccc", "padding": 10},
        ),
    ],
    style={"padding": 50},
)


@app.callback(
    Input("normal-set-props", "n_clicks"),
)
def test_normal_set_props(nClicks):

    p = Patch()
    p += ", extra value"

    set_props("normal-set-props-result", {"children": p})


@app.callback(
    Input("websocket-set-props", "n_clicks"),
    websocket=True,
)
def test_websocket_set_props(nClicks):

    p = Patch()
    p += ", extra value"

    set_props("websocket-set-props-result", {"children": p})


if __name__ == "__main__":
    app.run(debug=True)

Error message output from the terminal:

Task exception was never retrieved
future: <Task finished name='Task-17' coro=<set_props.<locals>._send_props() done, defined at D:\Miniforge\envs\dash-demos\Lib\site-packages\dash\_callback_context.py:371> exception=TypeError('Object of type Patch is not JSON serializable')>
Traceback (most recent call last):
  File "D:\Miniforge\envs\dash-demos\Lib\site-packages\dash\_callback_context.py", line 373, in _send_props
    await ws.set_prop(_id, prop_name, value)
  File "D:\Miniforge\envs\dash-demos\Lib\site-packages\dash\backends\base_server.py", line 429, in set_prop
    await self._send_json(
  File "D:\Miniforge\envs\dash-demos\Lib\site-packages\dash\backends\_fastapi.py", line 98, in _send_json
    await self._websocket.send_json(data)
  File "D:\Miniforge\envs\dash-demos\Lib\site-packages\starlette\websockets.py", line 174, in send_json
    text = json.dumps(data, separators=(",", ":"), ensure_ascii=False)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "D:\Miniforge\envs\dash-demos\Lib\json\__init__.py", line 238, in dumps
    **kw).encode(obj)
          ^^^^^^^^^^^
  File "D:\Miniforge\envs\dash-demos\Lib\json\encoder.py", line 200, in encode
    chunks = self.iterencode(o, _one_shot=True)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "D:\Miniforge\envs\dash-demos\Lib\json\encoder.py", line 258, in iterencode
    return _iterencode(o, 0)
           ^^^^^^^^^^^^^^^^^
  File "D:\Miniforge\envs\dash-demos\Lib\json\encoder.py", line 180, in default
    raise TypeError(f'Object of type {o.__class__.__name__} '
TypeError: Object of type Patch is not JSON serializable

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions