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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions