A nonexistent object was used in an `Output` of a Dash callback.?

Hi guys, getting the following error and not sure why:

A nonexistent object was used in an Output of a Dash callback. The id of this object is sidebar_container and the property is `children.

Currently building a multipage app with 4 pages. The last page, contains a callback that contains 'sidebar_container:

callback(
    Output("sidebar_container", "children"),
    Output("status_main_section", "children"),
    Output('summary_map_unit_clicked_value', 'clear_data'),
    Output('status_unit_clicked', 'data'),
    Input({'type': 'list-group-item', 'index': ALL},'n_clicks'),
    Input("jobsite-dropdown", "value"),
    State('summary_map_unit_clicked_value', 'data')
    # State("list-group", "children"),
)

def refresh(n_clicks_list, job_site, summary_map_unit_clicked):

    data_processor = get_data_processor()
    ....
return _build_sidebar(job_site, unitname), _build_main_section(job_site, unitname), True, unitname

The layout for this page is

layout = html.Div(

    [ dbc.Row(  
            [
                dbc.Col(html.Div(id="sidebar_container"), width=3),
                dbc.Col(html.Div(id="status_main_section"), width=9),
            ],className="mt-3",
        )
    ],
)

This last page doesnt throw this error, but all other pages do. Not sure why the other pages care about this sidebar_container. All pages share a job-site dropdown which gets built dynamically, and i can only presume that this is triggering the callback on the last page even if im not on it.

Any ideas?

1 Like

Bit more investigation shows the error always happens when returning the jobsite_dropdown_html:

Callback that refreshes the site when a data update is trigger

@callback(
Output(ā€œjobsite_dropdown_containerā€, ā€œchildrenā€),
Output(ā€œlast_data_refresh_containerā€, ā€œchildrenā€),
Output(ā€œdata_updated_flagā€, ā€œdataā€),
Input(ā€˜last_data_refresh_store’, ā€˜data’),
Input(ā€˜data_refresh_interval’, ā€˜n_intervals’),
Input(ā€˜dp-toggle-switch’, ā€˜value’))
def render_sub_menu_content(data_refresh_n_clicks:int, n_intervals:int, toggle_value ):

# callback flag to indicate if data was updated
data_updated = False

# Get button id if a button was clicked
trigger_id = None

ctx = dash.callback_context
if ctx.triggered:

    trigger_id = ctx.triggered[0]['prop_id'].split('.')[0]

data_processor_type = str(os.getenv('DATA_PROCESSOR'))

# Refresh data if data refresh button was clicked or refresh interval triggered
if trigger_id in ['last_data_refresh_store', 'data_refresh_interval', 'dp-toggle-switch']:

    if toggle_value == True:
        data_processor_type = strings.FIRSTORE_PROCESSOR

    else:
        data_processor_type = strings.FTP_PROCESSOR

    set_data_processor_type(data_processor_type)
    refresh_data_processor()

    data_updated  = True

data_processor = get_data_processor()
last_data_refresh_html = build_last_data_refresh(data_processor.last_data_refresh)
jobsite_dropwdown_html = build_jobsite_dropdown()

return jobsite_dropwdown_html, last_data_refresh_html, data_updated

No idea whay it throws the following error after the return statement: ā€œA nonexistent object was used in an Output of a Dash callback. The id of this object is sidebar_container' and the property is children`ā€

1 Like

Did you ever get a solution for this? I’m facing a the exact same problem

No I still get the error message but everything works fine. I presume it’s a bug in plotlys multi-page app functionality

You get an error but it still functions as intended? Mine doesn’t at all ;(

Anyone else solved this? getting the same error yet I defined the dropdown in the pages layout?

Are you using similar pattern matching callbacks on the other pages?

In my app.py I have a datepicker, button and dcc.Store, in the page_1 I have a dropdown and a callback which takes the button nclicks and datepicker from app.py as inputs to update the dropdown in the page_1 as an output. The dropdown is what is raising the error. I noticed that if I run the app with debug=False, the app still runs with no issues, it seems like this is just a flag which does not prevent the app from running, still annoying.

Do you have supress_callback_exceptions=True when you declare Dash?

Yes I do, so that prevents the error on initial load but once I click the button and select a date in the datepicker the error pops up again.

Can you share how you are declaring the button and the date picker?

sure, snippet of app.py

app.layout = html.Div([
    sidebar, navbar,
    dcc.Location(id="url"),
    dcc.Loading(id='load',
                type='default',
                children=[
                    html.Div([dcc.Store(id='data_memory'),
                              dcc.Store(id='position_data_memory_eur', storage_type='local'),
                              dcc.Store(id='position_data_memory_jpy', storage_type='local'),
                              dcc.Store(id='eur_traded_memory'),
                              dcc.Store(id='jpy_traded_memory'),
                              dcc.Store(id='ccy_memory')])
                ], fullscreen=True),
    dbc.Col(
        html.Div(html.H3('Select the first effective date for hedge rolls and refresh trades:', style={'fontSize': 20}),
                 style={'margin-top': '10px','padding-left': '130px'}),
        width={'size': 6, 'offset': 1}),

    dbc.Row([
        dbc.Col(html.Div(dcc.DatePickerSingle(id='date_picker',
                                              max_date_allowed=dt.date(dt.today()),
                                              initial_visible_month=dt.date(dt.today()),
                                              display_format='MMM Do, YY',
                                              placeholder='Select date',
                                              persistence=True,
                                              persistence_type='session',
                                              persisted_props=['date'],

                                              style={'margin-bottom': '10px','padding-left': '130px'})),
                width={'size': 1, 'offset': 1}),
        dbc.Col(html.Div(
            dbc.Button("Refresh Trades", id="button_eur", className="me-1"), style={'margin-top': '6px'}),
            width={'size': 2, 'offset': 1})
    ]
    ), content])

snippet of one of the pages

dash.register_page(
    __name__,
    path='/fx-points-tracker',
    title='Executed FX Points Tracker',
    name='Executed FX Points Tracker'
)

layout = html.Div([
    html.Hr(),
    html.H3("EXECUTED FX POINTS TRACKER"),
    html.Hr(),
    dbc.Row(
        dbc.Col(
            html.Div(html.H3('Select the traded currency and fund to plot:', style={'fontSize': 20}),
                     style={'padding-left': '10px', 'margin-top': '20px'}),
            width={'size': 6})),

    # File selection dropdown
    dbc.Row(
        dbc.Col(
            html.Div(dcc.Dropdown(id='ccy_dropdown',
                                  multi=False,
                                  placeholder='Select currency'),
                     style={'padding-left': '10px'}),
            width={'size': 2})),
    dbc.Row(
        dbc.Col(
            html.Div(dcc.Dropdown(id='fund_dropdown',
                                  multi=False,
                                  placeholder='Select fund',
                                  options=[{'label': c, 'value': c} for c in ['INTLAGG', 'TIB2']],
                                  value='INTLAGG'),
                     style={'padding-left': '10px'}),
            width={'size': 2})),

    dbc.Row(
        dbc.Col(
            html.Div(
                dcc.Graph(id='fx_points_fig', style={'width': '95vh', 'height': '95vh'}
                          ),
                style={'margin-top': '50px', 'width': '95%'}
            )
        )
    )
]
)


@callback([Output('data_memory', 'data'), Output('ccy_dropdown', 'options')],
          [Input('button_eur', 'n_clicks'), State('date_picker', 'date')], prevent_initial_call=True,
          background=True, cache_args_to_ignore=[0])
def update_latest_trades(but, date_value):
    if date_value is None or but is None:
        raise PreventUpdate
    try:

         long running data extract from API...

         return data, dropdown_options

    except:
        return None, None

I pretty much copied the demos provided by @AnnMarieW in terms of structure of the pages.

@AnnMarieW wondering if you have encountered the above before?

Hi @nickmuchi I haven’t encountered that when also adding supress_callback_exceptions=True as suggested by @Croll12.

Do you get the same error when you run the examples? Can you make a minimal example that reproduces the error?

A snippet of the example:

I have 2 pages, app.py and pages_1,

app.py has 3 components, a button, date picker and Store. The button and date picker are BOTH used as Inputs of a callback in pages_1. Pages_1 will then use those inputs to run a process which updates a dropdown in pages_1 layout (the ā€œnon-existent componentā€) and the Store in app.py. That is pretty much it in a nutshell

app.py

import os
import dash
from dash import DiskcacheManager, page_container, page_registry
import dash_bootstrap_components as dbc
from datetime import datetime as dt
from dash.exceptions import PreventUpdate
from uuid import uuid4
import diskcache
from variables import *
from app_functions import *

launch_uid = uuid4()


cache = diskcache.Cache(r".../")
background_callback_manager = DiskcacheManager(cache, cache_by=[lambda: launch_uid], expire=100)


# default bootstrap theme
app = dash.Dash(__name__, use_pages=True, external_stylesheets=[dbc.themes.BOOTSTRAP], suppress_callback_exceptions=True,
                background_callback_manager=background_callback_manager)

# the style arguments for the sidebar. We use position:fixed and a fixed width
SIDEBAR_STYLE = {}

# the styles for the main content position it to the right of the sidebar and
# add some padding.
CONTENT_STYLE = {}

sidebar = html.Div(
    [
        html.Br(),
        html.Br(),
        html.A(
            html.Img(
                src=app.get_asset_url('../'), height="150px"
            ),
            title="ME "
        ),
        html.Hr(),
        dbc.Nav(
            [
                dbc.NavLink("Home", href="/", active="exact"),
                dbc.NavLink("Pages 1", href="/pages_1", active="exact")
            ],
            vertical=True,
            pills=True,
        ),
    ],
    style=SIDEBAR_STYLE,
)

navbar = dbc.Navbar()

# content from pages
content = html.Div(dash.page_container, style=CONTENT_STYLE)

app.layout = html.Div([
    sidebar, navbar,
    dcc.Location(id="url"),
    dcc.Loading(id='load',
                type='default',
                children=[
                    html.Div([dcc.Store(id='data_memory'),
                              dcc.Store(id='position_data_memory_eur', storage_type='local'),
                              dcc.Store(id='position_data_memory_jpy', storage_type='local'),
                              dcc.Store(id='eur_traded_memory'),
                              dcc.Store(id='jpy_traded_memory'),
                              dcc.Store(id='ccy_memory')])
                ], fullscreen=True),
    dbc.Col(
        html.Div(html.H3('Select the first effective:', style={'fontSize': 20}),
                 style={'margin-top': '10px','padding-left': '130px'}),
        width={'size': 6, 'offset': 1}),

    dbc.Row([
        dbc.Col(html.Div(dcc.DatePickerSingle(id='date_picker',
                                              max_date_allowed=dt.date(dt.today()),
                                              initial_visible_month=dt.date(dt.today()),
                                              display_format='MMM Do, YY',
                                              placeholder='Select date',
                                              persistence=True,
                                              persistence_type='session',
                                              persisted_props=['date'],

                                              style={'margin-bottom': '10px','padding-left': '130px'})),
                width={'size': 1, 'offset': 1}),
        dbc.Col(html.Div(
            dbc.Button("Refresh Trades", id="button_eur", className="me-1"), style={'margin-top': '6px'}),
            width={'size': 2, 'offset': 1})
    ]
    ), content])



if __name__ == "__main__":
    app.run(host='tz', port=8052, debug=True)

pages_1.py

import dash
from dash import dcc, html, callback
import dash_bootstrap_components as dbc
from dash.dependencies import Input, Output, State
from dash.exceptions import PreventUpdate
from app_functions import get_api_data, generate_fx_points_graph
from variables import *
import plotly_express as px

dash.register_page(
    __name__,
    path='/pages_1',
    title='Pages 1',
    name='Pages 1'
)

layout = html.Div([
    html.Hr(),
    html.H3("EXE"),
    html.Hr(),
    dbc.Row(
        dbc.Col(
            html.Div(html.H3('Select the traded:', style={'fontSize': 20}),
                     style={'padding-left': '10px', 'margin-top': '20px'}),
            width={'size': 6})),

    # File selection dropdown
    dbc.Row(
        dbc.Col(
            html.Div(dcc.Dropdown(id='ccy_dropdown',
                                  multi=False,
                                  placeholder='Select currency'),
                     style={'padding-left': '10px'}),
            width={'size': 2})),
    dbc.Row(
        dbc.Col(
            html.Div(dcc.Dropdown(id='fund_dropdown',
                                  multi=False,
                                  placeholder='Select fund',
                                  options=[{'label': c, 'value': c} for c in ['INT', 'T2']],
                                  value='INT'),
                     style={'padding-left': '10px'}),
            width={'size': 2})),

    dbc.Row(
        dbc.Col(
            html.Div(
                dcc.Graph(id='fx_points_fig', style={'width': '95vh', 'height': '95vh'}
                          ),
                style={'margin-top': '50px', 'width': '95%'}
            )
        )
    )
]
)

@callback([Output('data_memory', 'data'), Output('ccy_dropdown', 'options')],
          [Input('button_eur', 'n_clicks'), State('date_picker', 'date')], prevent_initial_call=True)  #background=True, cache_args_to_ignore=[0]
def update_latest_trades(but, date_value):

             df = long_running_api_call

            
            ccy_options = sorted(df['sec'].unique().tolist())
            ccy_options_graph = [{'label': c, 'value': c} for c in ccy_options]

            return datasets, ccy_options_graph

    except:
        return None, None

@callback(Output('fx_points_fig', 'figure'),
          [Input('ccy_dropdown', 'value'), Input('button_eur', 'n_clicks'),
           Input('fund_dropdown', 'value'), State('data_memory', 'data'), State('ccy_memory', 'data')])
def generate_fx_points_table(ccy, n, fund, data, data_wmr):
    if ccy is None:
        raise PreventUpdate

    df = generate_values
    fig = px.scatter(df, x='Date', y="Points")

    return fig

Hope that makes sense, thanks for your help

Sorry, it doesn’t make sense. I know you also included some code earlier, but can you make a self contained complete minimal example that I can simply copy, paste and run locally to duplicate the same error you are seeing?

Sure, hope the below works:

app.py

import dash
from dash import html, dcc
import dash_bootstrap_components as dbc
from datetime import datetime as dt

# default bootstrap theme
app = dash.Dash(__name__, use_pages=True, external_stylesheets=[dbc.themes.BOOTSTRAP], suppress_callback_exceptions=True)

#sidebar
SIDEBAR_STYLE = {
    "position": "fixed",
    "top": 0,
    "left": 0,
    "bottom": 0,
    "width": "16rem",
    "padding": "2rem 1rem",
    "color": "#7F7F7F",
    "background-color": "#EBEBEB"}

# the styles for the main content position it to the right of the sidebar and
# add some padding.
CONTENT_STYLE = {
    "margin-left": "18rem",
    "margin-right": "2rem",
    "padding": "2rem 1rem",}

sidebar = html.Div(
    [
        html.Hr(),
        dbc.Nav(
            [
                dbc.NavLink("Home", href="/", active="exact"),
                dbc.NavLink("Pages 1", href="/pages_1", active="exact")
            ],
            vertical=True,
            pills=True,
        ),
    ],
    style=SIDEBAR_STYLE,
)

navbar = dbc.Navbar()

# content from pages
content = html.Div(dash.page_container, style=CONTENT_STYLE)

app.layout = html.Div([
    sidebar, navbar,
    dcc.Location(id="url"),
    dcc.Loading(id='load',
                type='default',
                children=[
                    html.Div([dcc.Store(id='data_memory'),
                              dcc.Store(id='ccy_memory')])
                ], fullscreen=True),
    dbc.Col(
        html.Div(html.H3('My App:', style={'fontSize': 20}),
                 style={'margin-top': '10px','padding-left': '130px'}),
        width={'size': 6, 'offset': 1}),

    dbc.Row([
        dbc.Col(html.Div(dcc.DatePickerSingle(id='date_picker',
                                              max_date_allowed=dt.date(dt.today()),
                                              initial_visible_month=dt.date(dt.today()),
                                              display_format='MMM Do, YY',
                                              placeholder='Select date',
                                              persistence=True,
                                              persistence_type='session',
                                              persisted_props=['date'],

                                              style={'margin-bottom': '10px','padding-left': '130px'})),
                width={'size': 1, 'offset': 1}),
        dbc.Col(html.Div(
            dbc.Button("Refresh Trades", id="button_eur", className="me-1"), style={'margin-top': '6px'}),
            width={'size': 2, 'offset': 1})
    ]
    ), content])



if __name__ == "__main__":
    app.run(debug=True)

pages_1.py

import dash
from dash import dcc, html, callback
import dash_bootstrap_components as dbc
from dash.dependencies import Input, Output, State
from dash.exceptions import PreventUpdate
import plotly_express as px
import pandas as pd

dash.register_page(
    __name__,
    path='/pages_1',
    title='Page 1',
    name='Page 1'
)

layout = html.Div([
    html.Hr(),
    html.H3("Page 1"),
    dbc.Row(
        dbc.Col(
            html.Div(html.H3('DropDown Below:', style={'fontSize': 20}),
                     style={'padding-left': '10px', 'margin-top': '20px'}),
            width={'size': 6})),

    # File selection dropdown
    dbc.Row(
        dbc.Col(
            html.Div(dcc.Dropdown(id='ccy_dropdown',
                                  multi=False,
                                  placeholder='Select currency'),
                     style={'padding-left': '10px'}),
            width={'size': 2})),
    dbc.Row(
        dbc.Col(
            html.Div(dcc.Dropdown(id='fund_dropdown',
                                  multi=False,
                                  placeholder='Select fund',
                                  options=[{'label': c, 'value': c} for c in ['One', 'Two']],
                                  value='One'),
                     style={'padding-left': '10px'}),
            width={'size': 2})),

    dbc.Row(
        dbc.Col(
            html.Div(
                dcc.Graph(id='fx_points_fig', style={'width': '95vh', 'height': '95vh'}
                          ),
                style={'margin-top': '50px', 'width': '95%'}
            )
        )
    )
]
)

@callback([Output('data_memory', 'data'), Output('ccy_dropdown', 'options')],
          [Input('button_eur', 'n_clicks'), State('date_picker', 'date')], prevent_initial_call=True) 
def update_latest_trades(but, date_value):
    if date_value is None or but is None:
        raise PreventUpdate

    try:

         datasets = {'data': 3}
         dd_options = [{'label': c, 'value': c} for c in ['One','Two']]

         return datasets, dd_options

    except:
        return None, None

@callback(Output('fx_points_fig', 'figure'),
          [Input('ccy_dropdown', 'value'), Input('button_eur', 'n_clicks'),
          Input('fund_dropdown', 'value'), State('data_memory', 'data')],prevent_initial_call=True)
def generate_fx_points_table(ccy, n, fund, data):
    if ccy is None:
        raise PreventUpdate

    df = pd.DaraFrame(data=[['One',2,3],['Two',4,5]], columns = ['Fund','Currency','Points'])

    fig = px.scatter(df.loc[df['Fund'].isin([fund])], x='Currency', y="Points")

    return fig

Tried to make the example as min as possible, thanks a lot for your help here. The app was working before I tried using the dash pages. Looks like there was a similar discussion here but no solution: šŸ“£ Dash v1.11.0 Release - Introducing Pattern-Matching Callbacks - #2 by chriddyp

Hi @nickmuchi This is a good topic, and thanks for finding that detailed discussion - There’s a good summary in this post: šŸ“£ Dash v1.11.0 Release - Introducing Pattern-Matching Callbacks - #25 by alexcjohnson, and it’s worth repeating this point here:

  • If any Input items are present (or the multi-item exception), we will fire the callback, and it’s an error if any of the Output or State items is missing.

With multi-page apps, components in the layout of app.py are available to all pages. If a component is in a page layout, then it’s only present when you are on that page.

So, the issue is in this callback:

In this callback, all components in the Inputs and Outputs are in app.py except for the dropdown which is only in page1. So if you click on the button while you are on page1, there is no error. However, if you click on the button while on the home page, the dropdown does not exist, so you will see the error.

You could move the button and datepicker to page1. However, I’m guessing that you are using those to refresh data and share it between pages. In that case, I recommend splitting the callback. One to update the data, then use a dcc.Store as an Input to trigger the update of the dropdown options.

Let me know if you have more questions :slight_smile:

3 Likes

That makes sense, thanks for explaining that. Just one point of clarification, should I move the callback for updating the data to app.py? Then I can have another callback for only the dropdown in page_1? You are right, the data_memory dcc.Store is responsible for sharing data across all pages.

It actually doesn’t matter what file the callbacks are in. It just depends on how you like to organize your project. I often put callbacks that apply to all pages in app.py. Some people put all callbacks in a separate file.

1 Like