Component with duplicate id doesn't raise a warning if created in a callback - overwrites the callback(s) the first component was part of
Open
@T4rk1n is already working on this.
Since Sep 9, 2025.
bug
cs
P1
- Dominant language
- Python
- Stars
- 24.4k
- Forks
- 2.3k
- Avg merge
- 2d 7h
- Merged PRs (30d)
- 13
Description
Description of the issue
https://github.com/user-attachments/assets/821b9dd9-acc1-44b6-a9b5-c52a22778149
- The issue happens both if the affected callback (the one that uses the "duplicated" id as Input, Output or State) is defined with
@app.callbackor@dash.callback. suppress_callback_exceptions=Trueis not set inapp = Dash(...).- The rest of the callbacks (both defined with
@app.callbackand@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.getElementByIdin the Console, the component that's identified is the one that appears first in the html.
Case 1: sample code (original button is first)
Case 2: new 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)
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.