Hi Dash Community,
I’m experiencing an issue where app.validation_layout
doesn’t prevent callback validation errors when using dynamic layouts with the Pages module in Dash 3.1.1.
Problem Description
According to the documentation, app.validation_layout
should allow us to define all possible components to avoid callback validation errors in multi-page apps. However, this doesn’t seem to work with dynamic layouts in the Pages module.
Minimal Reproducible Example - see the code at the end.
Expected Behavior
Based on the documentation, defining app.validation_layout with all possible components should prevent callback validation errors, even for components that are conditionally rendered.
Actual Behavior
Despite defining all components in app.validation_layout, I still get this error:
*Attempting to connect a callback Output item to component: “output-evening” *
*but no components with that id exist in the layout. If you are assigning *
*callbacks to components that are generated by other callbacks (and therefore *
*not in the initial layout), you can suppress this exception by setting *
suppress_callback_exceptions=True
.
Current Workaround
The only solution is to use suppress_callback_exceptions=True, but according to the documentation, app.validation_layout should make this unnecessary.
Questions
Is this expected behavior with the Pages module and dynamic layouts?
Is app.validation_layout supposed to work differently with Pages than with single-file apps?
Should the documentation be updated to clarify this limitation?
Environment
Dash: 3.1.1
Python: 3.13
OS: Windows 11
Any insights would be greatly appreciated!
- app.py
from dash import Dash, html, dcc, page_container
# Initialize the app with pages module
app = Dash(__name__, use_pages=True)
# Define the main layout
app.layout = html.Div([
html.H1("Welcome to Our App"),
dcc.Link("Page 1", href="/page1"),
html.Br(),
dcc.Link("Page 2", href="/page2"),
html.Hr(),
page_container
])
# Create a validation layout with ALL possible components
app.validation_layout = html.Div([
# Main app components
app.layout,
# Morning layout components
html.Div([
html.H3("Morning Layout"),
dcc.Input(id="input-morning", type="text"),
html.Div(id="output-morning")
]),
# Evening layout components
html.Div([
html.H3("Evening Layout"),
dcc.Dropdown(id="dropdown-evening", options=['Tea', 'Coffee']),
html.Div(id="output-evening")
]),
html.Div([
html.H2("Welcome to Page 1"),
dcc.Input(id="input-p1", placeholder="Enter something...", type="text"),
html.Div(id="output-p1")
]),
])
if __name__ == '__main__':
app.run(debug=True)
- pages/page1.py
from dash import register_page, html, dcc, Input, Output, callback
register_page(__name__, path="/page1", name="Page 1")
layout = html.Div([
html.H2("Welcome to Page 1"),
dcc.Input(id="input-p1", placeholder="Enter something...", type="text"),
html.Div(id="output-p1")
])
@callback(Output("output-p1", "children"), Input("input-p1", "value"))
def update_output(value):
return f"You entered: {value}" if value else ""
- pages/page2.py - dynamic layout
from dash import register_page, html, dcc, Input, Output, callback
import datetime
register_page(__name__, path="/page2", name="Page 2")
def layout():
# Dynamic layout logic based on time of day
hour = datetime.datetime.now().hour
if hour < 12:
return html.Div([
html.H3("Morning Layout"),
dcc.Input(id="input-morning", type="text", placeholder="Good morning!"),
html.Div(id="output-morning")
])
else:
return html.Div([
html.H3("Evening Layout"),
dcc.Dropdown(['Tea', 'Coffee'], id="dropdown-evening", placeholder="Choose your drink"),
html.Div(id="output-evening")
])
@callback(Output("output-morning", "children"), Input("input-morning", "value"))
def handle_morning(val):
return f"Rise and shine: {val}" if val else ""
@callback(Output("output-evening", "children"), Input("dropdown-evening", "value"))
def handle_evening(drink):
return f"Unwinding with: {drink}" if drink else ""