-
-
Notifications
You must be signed in to change notification settings - Fork 2.2k
Open
Description
Description of the issue
Screen.Recording.2025-08-29.at.13.55.06.mov
- The issue happens both if the affected callback (the one that uses the "duplicated" id as Input, Output or State) is defined with
@app.callback
or@dash.callback
. suppress_callback_exceptions=True
is not set inapp = Dash(...)
.- The rest of the callbacks (both defined with
@app.callback
and@dash.callback
) keep working after the component generation (not shown in the video). - The component that the affected callback uses is the newest one.
- If, after generating the second component, I do
document.getElementById
in the Console, the component that's identified is the one that appears first in the html.
Case 1: sample code (original button is first)
Expected behavior
Component id validation should also happen when new components are added to the layout. An error like this should be shown in the debug menu or the logs:
dash.exceptions.DuplicateIdError: Duplicate component id found in the initial layout: `b3`
Code to replicate the issue
dash==3.2.0
import dash
from dash import dcc, html, Input, Output, State, callback, ctx
app = dash.Dash(__name__)
app.layout = html.Div([
html.H3("callback 1: @app.callback, output=div1"),
html.Button(id="b1", children="Trigger callback 1"),
html.Div(id="div1", children="callback 1 not triggered yet"),
####
html.H3("callback 2: @callback, output=div2"),
html.Button(id="b2", children="Trigger callback 2"),
html.Div(id="div2", children="callback 2 not triggered yet"),
###
html.H3("callback 3: @app.callback, output=div3"),
html.Button(id="b3", children="Trigger callback 3 (initial n_clicks=20)", n_clicks=20),
html.Div(id="div3", children="callback 3 not triggered yet"),
####
html.Br(),
html.Button(id="b4", children="Generate component with duplicate id (b3)"),
html.Br(),
html.Div(id="div4")
])
@app.callback(
Output("div1", "children"),
Input("b1", "n_clicks"),
prevent_initial_call=True
)
def update_div1_with_b1(b1):
return f"Callback 1 triggered by {ctx.triggered_id} and {b1} clicks"
@callback(
Output("div2", "children"),
Input("b2", "n_clicks"),
prevent_initial_call=True
)
def update_div1_with_b2(b2):
return f"Callback 2 triggered by {ctx.triggered_id} and {b2} clicks"
@callback(
Output("div3", "children"),
Input("b3", "n_clicks"),
prevent_initial_call=True
)
def update_div3(b3):
return f"Callback 3 triggered by {ctx.triggered_id} and {b3} clicks"
@callback(
Output("div4", "children"),
Input("b4", "n_clicks"),
prevent_initial_call=True
)
def update_div4(b4):
return html.Button(id="b3", children="Button with duplicate id (b3)", n_clicks=0),
if __name__ == '__main__':
app.run(debug=True)
Metadata
Metadata
Assignees
Labels
No labels