Hi @etonblue
Have you tried adding supress_callback_excpetions=True
?
app = Dash(__name__, use_pages=True, suppress_callback_exceptions=True)
Hi @etonblue
Have you tried adding supress_callback_excpetions=True
?
app = Dash(__name__, use_pages=True, suppress_callback_exceptions=True)
Yes. Both in the app definition and in the individual callbacks.
Oh yes - you mentioned that you already tried supress_callback_exceptions = True
The only way I’ve been able to replicate the issue is if there is a single callback with inputs from two different pages. But I’m not seeing that case with what you’ve posted so far. If you are able to make a MRE, I’d love to see it.
Hi @etonblue , just to make sure: if you coment out the callback on page 6, the error is not thrown?
Did you try preventing the callback on page 6 at startup? Or does the error pop up constantly?
The relevant parts of the two callbacks look something like this (the real ones are quite a bit more complicated). get_years() is a function that returns a list from a sqlite database.
@callback(
Output("year-dropdown", "options"),
Output("year-dropdown", "value"),
Input("entity-dropdown", "value"),
Input("year-dropdown", "value"),
Input("store", "data"),
# supress_callback_exceptions = True
)
def set_year_dropdown_options(entity: str, year: str, store: str):
if store == "Red":
years = get_years(entity,"Red")
else:
years = get_years(entity,"Green)
max_years = 5
number_of_years_to_display = len(years) if len(years) <= max_years else max_years
dropdown_years = years[0:number_of_years_to_display]
first_available_year = dropdown_years[0]
earliest_available_year = dropdown_years[-1]
if year is None:
year_value = str(first_available_year)
elif int(year) < int(earliest_available_year):
year_value = str(earliest_available_year)
elif int(year) > int(first_available_year):
year_value = str(first_available_year)
else:
year_value = str(year)
year_options=[
{"label": str(y), "value": str(y)}
for y in dropdown_years
]
return year_options, year_value
On page6, we need years to change depending on whether the user selects “Red” or “Green.” What I am trying to do is store the value “Red” or “Green” in “store” so that I can use it in app.py for the dropdown_options callback. Again, this callback is a bit more complicated than the sample below, but hopefully this gets you the gist.
@callback(
Output("radio-colors", "options"),
Output("radio-colors"," value"),
Output("store", "data"),
Input("entity-dropdown", "value"),
Input("radio-colors", "value"),
# supress_callback_exceptions = True,
# prevent_initial_call=True
)
def radio_type_selector(entity: str, color_value: str):
color_options = [
{"label": "Red", "value": "red"},
{"label": "Green", "value": "green"}
]
if color_value in ["Red","Green"]:
current_color = color_value
else:
current_color = "Red"
store_value = current_color
return color_options, current_color, store_value
The app.py layout is described in my first post. dcc.Store is not used as an Input or Output anywhere else in the app.
If I delete the callback on page6 the error goes away.
If I remove dcc.store from the layout, the error goes away.
Using prevent_initial_call = True in the page6 callback and/or in the year_dropdown callback does not fix the issue.
There are 28 callbacks total in the layout on ten pages. Everything works, including the callbacks described above. The only issue is the error. I am literally banging my head against a table in Starbucks.
If all else fails can I just ignore it?
Does it matter whether the layouts in each page are variables or functions? Right now they are all functions:
app.py:
def layout():
return html.Div(
[
... stuff ...
]
)
app.layout = layout
and every other page is just
def layout():
return html.Div(
[
... stuff ...
]
)
I’ve tried setting all layouts to a variable, eg.:
app.layout = html.Div(
[
... stuff ...
]
)
# app.layout = layout
for app.py and
app.layout = html.Div(
[
... stuff ...
]
)
for everything else, but it doesn’t seem to do anything except breaking my subnav() functionality. Which is now making me think. I have two pages are displayed as part of a second layer of navigation. They are defined thusly:
def subnav():
return html.Div(
dbc.Nav(
[
dbc.NavLink(
page['name'],
href=page['path'],
className = 'tab',
active='exact'
)
for page in dash.page_registry.values()
if page["path"].startswith("/subnav")
],
),
)
and displayed in the layout of the two pages as:
html.Div(subnav(), id="subnav", className="tabs")
One of these pages is the page with dcc.store. Could this subnav() function be messing with dcc.store somehow?
Also, when I change the layouts of those two pages to variables, subnav() stops working.
Still working on that MRE.
I would say yes.
I ran into the exact same problem a while ago. I did not observe any erroneous behavior in my app. But since it bothered me , I did try to come up with an MRE but I actually never achieved to replicate this error.
Right now, I don’t have this error popping up anymore, but I can’t remember what I changed to achieve this
Did you try printing the triggering ID?
print(ctx.triggered_id)
I think I explicitly omitted the firing of the callback not just setting prevent_initial_call=True
but also including an If/else even though it should not be necessary. Something like this :
def update(a, b):
if not a and not b:
raise PreventUpdate
...
...
@etonblue try putting the dcc.Store only in the main app.py layout.
Well, I wish I could say that I figured out how to fix the error, but I did not. Instead I rewrote my navigation code and moved it into my top level app layout (which is probably what I should have done in the first place) into a single callback, so that the values of the various radio button components have access to each other.
However this raises another question, which I ask here:
How long is too long for a callback function?:
Thanks for all the help everyone.