dash icon indicating copy to clipboard operation
dash copied to clipboard

[BUG] callback in infinite loop but only triggered once

Open yxc8 opened this issue 1 year ago • 4 comments

Here is a minimal example of how it breaks.

Error appears as the app keeps loading forever and debug mode suggests 'Maximum Depth Exceeded', indicating the callback is in an infinite loop. However, printing out the trigger_id suggests the callback is only triggered once and everything before return is ran once. This is almost impossible to debug since the messages don't give any actionable feedback.

The real problem seems to be the 0 Amount: changing it to non-zero OR changing if x['Type'] == 'C' to if x['Type'] == 'C' and float(x['Amount']) fixes the front-end problem.

However, I don't understand why this would be a problem if get_data() is only called once in the callback and the callback is only triggered once. Maybe it is stuck updating 0 to -0 and -0 to 0 forever? But what is causing *(-1) to be applied over and over again when it is only supposed to be called once?

It seems to relate to componentDidUpdate function here: Dash GitHub Link, but I don't have any JS knowledge to further understand this. Please help, thanks!

import dash_ag_grid as dag
import pandas as pd
from dash import dcc, html, Input, Output, no_update
import dash

def get_data():
    df = pd.DataFrame([{'Amount': 11111.0, 'Type': 'C'}, {'Amount': 0.0, 'Type': 'C'}])
    df['Amount'] = df.apply(lambda x: float(x['Amount']) * (-1) if x['Type'] == 'C' else float(x['Amount']), axis=1)
    return df

app = dash.Dash(__name__)
app.layout = dcc.Loading([html.Div(id='placeholder'), dag.AgGrid(id='datatable', columnDefs=[{'field': 'Amount'}]),
                          dcc.Store(id='data_store', storage_type='session')])


@dash.callback(
    Output('placeholder', 'children'),
    Output('datatable', 'rowData'),
    Output('data_store', 'data'),
    Input('placeholder', 'children')
)
def update_table(dummy):
    # trigger_id = dash.callback_context.triggered[0]['prop_id'].split('.')[0]
    # trigger_property = dash.callback_context.triggered[0]['prop_id'].split('.')[1] if trigger_id else ""
    # print(f"Callback triggered: {trigger_id}, {trigger_property}")
    df_all = get_data()
    cached_data = df_all.to_dict('records')
    return no_update, df_all.to_dict('records'), cached_data


if __name__ == '__main__':
    app.run_server(debug=True)

yxc8 avatar Dec 25 '23 22:12 yxc8

Thank you for reporting this, @yxc8 . I can confirm that I'm getting the same error message, using your code. Like you said, if I update the amount to 0.5 -- {'Amount': 0.0, 'Type': 'C'} -- it seems to work. I'm using PyCharm, Windows 11, and the Brave browser.

Coding-with-Adam avatar Dec 26 '23 17:12 Coding-with-Adam

Hi @Coding-with-Adam On Ubuntu and Chrome I can't reproduce the error.

AnnMarieW avatar Dec 26 '23 17:12 AnnMarieW

Can I work on this issue?

SarthakNikhal avatar Jan 19 '24 19:01 SarthakNikhal

Hi @SarthakNikhal

Thanks for your offer to help!
One thing you could do is to see if you can reproduce the error. The code posted above works fine for me. If you do get an error, could you say what version of Dash, Pandas and Python you are using, or any other info that might help?

AnnMarieW avatar Jan 19 '24 22:01 AnnMarieW

Hi - we are tidying up stale issues and PRs in Plotly's public repositories so that we can focus on things that are most important to our community. If this issue is still a concern, please add a comment letting us know what recent version of our software you've checked it with so that I can reopen it and add it to our backlog. (Please note that we will give priority to reports that include a short reproducible example.) If you'd like to submit a PR, we'd be happy to prioritize a review, and if it's a request for tech support, please post in our community forum. Thank you - @gvwilson

gvwilson avatar Jul 25 '24 13:07 gvwilson