Dash Pages - Nonexistent object was used in an `Input`

Hi! I am trying to use Dash Pages, but I am getting the below error:

A nonexistent object was used in an `Input` of a Dash callback. The id of this object is `dataframe_picker` and the property is `value`. The string ids in the current layout are: [data_refresh_interval_component, data_refresh_signal, last_updated_timer, CV_interval_component, CV_signal, last_validated_timer, hourly_forecast_interval_component, hourly_forecast_signal, daily_forecast_interval_component, daily_forecast_signal, _pages_location, _pages_content, _pages_store, _pages_dummy]

My app is structured as such:

- app.py
- pages
   |-- alltime.py
   |-- today.py
   |-- home.py

This is in app.py:

# app instantiation
app = dash.Dash(__name__, use_pages=True,
                external_stylesheets=[dbc.themes.LUX],
                suppress_callback_exceptions=True)
server = app.server

# cache
CACHE_CONFIG = {
    'CACHE_TYPE': 'FileSystemCache',
    'CACHE_DIR': "cache/",
    'CACHE_THRESHOLD': 20
}
cache = Cache()
cache.init_app(app.server, config=CACHE_CONFIG)

app.layout = html.Div([
    html.H1('slrpEV Dashboard'),

    html.Div(
        [
            html.Div([
                dcc.Link(
                    f"All Time", href="/alltime"
                ),
                dcc.Link(
                    f"Today", href="/today"
                )
            ]),
            html.Div([
                dcc.Interval(
                    id="data_refresh_interval_component",
                    interval=60 * 60 * 1000,  # update every 60 minutes
                    n_intervals=0
                ),
                dcc.Store(id="data_refresh_signal"),
            ]),
            html.Div(
                id="last_updated_timer"
            ),
            html.Div([
                dcc.Interval(
                    id="CV_interval_component",
                    interval=14 * 24 * 60 * 60 * 1000,  # update every two weeks
                    n_intervals=0
                ),
                dcc.Store(id="CV_signal"),
            ]),
            html.Div(
                id="last_validated_timer"
            ),
            html.Div([
                dcc.Interval(
                    id="hourly_forecast_interval_component",
                    interval=60 * 60 * 1000,  # update every 60 minutes
                    n_intervals=0
                ),
                dcc.Store(id="hourly_forecast_signal"),
            ]),
            html.Div([
                dcc.Interval(
                    id="daily_forecast_interval_component",
                    interval=24 * 60 * 60 * 1000,  # update every day
                    n_intervals=0
                ),
                dcc.Store(id="daily_forecast_signal"),
            ]),
        ]
    ),
    dash.page_container,
])

# jump to present button
@app.callback(
    Output("date_picker", "start_date"),
    Output("date_picker", "end_date"),
    Input("jump_to_present_btn", "n_clicks")
)
def jump_to_present(button_press):
    return get_last_days_datetime(7), get_last_days_datetime(-1)


@app.callback(
    Output("daily_time_series", "figure"),
    Input("data_refresh_signal", "data"),
)
def display_daily_time_series(signal):
    # load data
    data = update_data().get("dataframes")
    data = data.get("todays_sessions")
    # plot figure
    fig = PlotDailySessionTimeSeries.plot_daily_time_series(data)
    return fig


@app.callback(
    Output("vehicle_pie_chart", "figure"),
    Input("data_refresh_signal", "data"),
)
def display_vehicle_pie_chart(signal):
    # load data
    data = update_data().get("dataframes")
    data = data.get("todays_sessions")
    # plot figure
    fig = PlotDailySessionEnergyBreakdown.plot_daily_energy_breakdown(data)
    return fig


@app.callback(
    Output("cumulative_energy_delivered", "figure"),
    Input("date_picker", "start_date"),
    Input("date_picker", "end_date"),
    Input("data_refresh_signal", "data")
)
def display_cumulative_energy_figure(start_date, end_date, signal):
    # load data
    data = update_data().get("dataframes").get("raw_data")
    # plot figure
    fig = PlotCumulativeEnergyDelivered.plot_cumulative_energy_delivered(
        data, start_date, end_date)
    return fig


@app.callback(
    Output("time_series_plot", "figure"),
    Output("last_updated_timer", "children"),
    Input("dataframe_picker", "value"),
    Input("quantity_picker", "value"),
    Input("date_picker", "start_date"),
    Input("date_picker", "end_date"),
    Input("toggle_forecasts", "value"),
    Input("data_refresh_signal", "data"),
    Input("hourly_forecast_signal", "data"),
    Input("daily_forecast_signal", "data"),
)
def display_main_figure(granularity, quantity, start_date, end_date, forecasts, data_signal, hourly_forecast_signal, daily_forecast_signal):
    # load data
    data = update_data().get("dataframes")
    data = data.get(granularity)
    # update refresh timestamp
    last_updated = update_data().get('last_updated_time')
    # plot main time series
    fig = PlotMainTimeSeries.plot_main_time_series(
        data, granularity, quantity, start_date, end_date)

    # plot predictions
    if forecasts:
        forecast_df = prediction_to_run(granularity)
        fig = PlotForecasts.plot_forecasts(
            fig, forecast_df, quantity, granularity)

    return fig, f"Data last updated at {last_updated}."


@app.callback(
    Output("num_sessions_user", "children"),
    Output("avg_duration_user", "children"),
    Output("freq_connect_time_user", "children"),
    Output("total_nrg_consumed_user", "children"),
    Input("daily_time_series", "hoverData"),
    prevent_initial_callback=True
)
def display_user_hover(hoverData):
    # place holder for no hover
    if hoverData is None:
        return "# of Sessions by User", "Avg. Stay Duration", "Frequent Connect Time", "Total Energy Consumed by User"
    # load data
    data = update_data().get("dataframes").get("raw_data")
    # get user ID
    userId = int(hoverData["points"][0]["customdata"][2])
    # get user hover data
    num_sessions, avg_duration, freq_connect, total_nrg = GetUserHoverData.get_user_hover_data(
        data, userId)

    text = (
        f"User has been here {num_sessions} times!",
        f"User charges on average {avg_duration} hours!",
        f"User usually charges: {freq_connect}",
        f"User has consumed {total_nrg} kWh to date!"
    )

    return text


@app.callback(
    Output("data_refresh_signal", "data"),
    Input("data_refresh_interval_component", "n_intervals"),
)
def data_refresh_interval(n):
    update_data()  # expensive process
    return n


@app.callback(
    Output("CV_signal", "data"),
    Output("last_validated_timer", "children"),
    Input("CV_interval_component", "n_intervals"),
)
def CV_interval(n):
    params = update_ml_parameters()  # expensive process
    # calculate new models with ML parameters
    return n, f"Parameters last validated {params['last_validated_time']}."


@app.callback(
    Output("hourly_forecast_signal", "data"),
    Input("hourly_forecast_interval_component", "n_intervals"),
    Input("data_refresh_signal", "data"),
)
def hourly_forecast_interval(n, signal):
    forecast_hourly()
    return n


@app.callback(
    Output("daily_forecast_signal", "data"),
    Input("daily_forecast_interval_component", "n_intervals"),
    Input("data_refresh_signal", "data"),
)
def daily_forecast_interval(n, signal):
    forecast_daily()
    return n


# Cached functions
@cache.memoize(timeout=3600)  # refresh every hour
def update_data() -> dict:

    print("Fetching data...")
    raw_data = FetchData.scan_save_all_records()

    print("Cleaning data...")
    cleaned_dataframes = CleanData.clean_save_raw_data(raw_data)

    print("Done!")
    return {"dataframes": cleaned_dataframes, "last_updated_time": datetime.now().strftime('%H:%M:%S')}


@cache.memoize(timeout=1209600)  # retrain every two weeks
def update_ml_parameters() -> dict:
    # get parameters
    hard_coded_params_hourly = {'energy_demand_kWh':
                                {'best_depth': 57, 'best_n_neighbors': 25},
                                'peak_power_W':
                                    {'best_depth': 57, 'best_n_neighbors': 23},
                                'avg_power_demand_W':
                                    {'best_depth': 57, 'best_n_neighbors': 25}
                                }
    hard_coded_params_daily = {'energy_demand_kWh':
                               {'order': (2, 0, 1),
                                'seasonal_order': (0, 1, 2, 7)},
                               'peak_power_W':
                               {'order': (1, 0, 0),
                                'seasonal_order': (0, 1, 2, 7)},
                               'avg_power_demand_W':
                               {'order': (2, 0, 1),
                                'seasonal_order': (0, 1, 2, 7)}
                               }
    best_params = {}
    best_params["hourlydemand"] = hard_coded_params_hourly
    best_params["dailydemand"] = hard_coded_params_daily

    # clear predictions
    CreateHourlyForecasts.save_empty_prediction_df()
    CreateDailyForecasts.save_empty_prediction_df()

    return {"best_params": best_params, "last_validated_time": datetime.now().strftime('%m/%d/%y %H:%M:%S')}

The Input id dataframe_picker is present in alltime.py. While it is true that the id dataframe_picker is not present in app.py, doesn’t Dash pages automatically validate the layout? Any help would be appreciated! Thank you!

Edit: Here are page files:

import dash
import dash_bootstrap_components as dbc
from dash import html, dcc
from dash.dependencies import Output, Input, State
import dash_daq as daq
import pandas as pd
from datetime import timedelta
from app_utils import get_last_days_datetime

dash.register_page(__name__)


layout = html.Div(
    [
        html.Div([
            html.Div([
                dcc.DatePickerRange(
                    id="date_picker",
                    clearable=True,
                    start_date=get_last_days_datetime(7),
                    end_date=get_last_days_datetime(0),
                    start_date_placeholder_text="mm/dd/yyyy",
                    end_date_placeholder_text="mm/dd/yyyy",
                    with_portal=False
                ),
            ],
                className="calendar"),
            html.Div([
                dcc.Dropdown(
                    id="dataframe_picker",
                    options=[
                        {'label': '5-Min', 'value': 'fivemindemand'},
                        {'label': 'Hourly', 'value': 'hourlydemand'},
                        {'label': 'Daily', 'value': "dailydemand"},
                        {'label': 'Monthly', 'value': 'monthlydemand'}
                    ],
                    value='hourlydemand',  # default value
                    clearable=False,
                    searchable=False
                ),
                dcc.Dropdown(
                    id="quantity_picker",
                    options=[
                        {'label': 'Energy Demand',
                         'value': 'energy_demand_kWh'},
                        {'label': 'Average Power Demand',
                         'value': 'avg_power_demand_W'},
                        {'label': 'Peak Power Demand',
                         'value': 'peak_power_W'}
                    ],
                    value='energy_demand_kWh',  # default value
                    clearable=False,
                    searchable=False
                ),
            ]),
            html.Button("Today", id="jump_to_present_btn"),
            daq.ToggleSwitch(
                label="Toggle Forecasts",
                value=False,
                id="toggle_forecasts",
            )
        ]),
        html.Div([
            dcc.Graph(
                id="time_series_plot",
                config={
                    "displaylogo": False,
                    "modeBarButtonsToAdd": ["hoverCompare", "hoverClosest"]
                }
            )
        ]),
        html.Div([
            "Cumulative Energy Delivered",
            dcc.Graph(
                id="cumulative_energy_delivered",
                config={
                    "displaylogo": False
                }
            ),
        ]),
    ]
)
import dash
import dash_bootstrap_components as dbc
from dash import html, dcc
import dash_daq as daq


dash.register_page(__name__)

layout = html.Div(
    [
        html.Div([
            html.Div([
                "Today's Sessions",
                dcc.Graph(
                    id="daily_time_series",
                    config={
                        "displaylogo": False,
                        "modeBarButtonsToAdd": ["hoverCompare", "hoverClosest"]
                    }
                ),
            ]),
            "User Information",
            html.Div([
                html.Li("# of Sessions by User",
                        id="num_sessions_user"),
                html.Li("Avg. Stay Duration", id="avg_duration_user"),
                html.Li("Frequent Connect Time",
                        id="freq_connect_time_user"),
                html.Li("Total Energy Consumed",
                        id="total_nrg_consumed_user")
            ],
                id='user-information',
            ),
            html.Div([
                "Energy Breakdown",
                dcc.Graph(
                    id="vehicle_pie_chart"
                )
            ]),
        ]),
    ],
)

Hi winstonchiong, welcome to the community. Can you post your alltime.py code and callback of app.py too? I think with it, everyone can understand your problem better.

1 Like

Done! Let me know what you make of this!

I can not represent your error because in your code have some def that did not show here so I can not use it to run. But with simpler code like below I did not see errors.

app.py

import dash
import dash_bootstrap_components as dbc
from dash import dcc
from dash import html
from dash.dependencies import Input, Output
from datetime import date

app = dash.Dash(__name__, use_pages=True,
                suppress_callback_exceptions=True)
server = app.server

app.layout = html.Div([
    html.H1('slrpEV Dashboard'),
    html.Div(
        [
            html.Div([
                dcc.Link(
                    f"All Time", href="/alltime"
                ),
                dcc.Link(
                    f"Today", href="/today"
                )
            ]),
            html.Div([
                dcc.Interval(
                    id="data_refresh_interval_component",
                    interval=60 * 60 * 1000,  # update every 60 minutes
                    n_intervals=0
                ),
                dcc.Store(id="data_refresh_signal"),
            ]),
            html.Div(
                id="last_updated_timer"
            ),
            html.Div([
                dcc.Interval(
                    id="CV_interval_component",
                    interval=14 * 24 * 60 * 60 * 1000,  # update every two weeks
                    n_intervals=0
                ),
                dcc.Store(id="CV_signal"),
            ]),
            html.Div(
                id="last_validated_timer"
            ),
            html.Div([
                dcc.Interval(
                    id="hourly_forecast_interval_component",
                    interval=60 * 60 * 1000,  # update every 60 minutes
                    n_intervals=0
                ),
                dcc.Store(id="hourly_forecast_signal"),
            ]),
            html.Div([
                dcc.Interval(
                    id="daily_forecast_interval_component",
                    interval=24 * 60 * 60 * 1000,  # update every day
                    n_intervals=0
                ),
                dcc.Store(id="daily_forecast_signal"),
            ]),
        ]
    ),
    dash.page_container,
])

# jump to present button
@app.callback(
    Output("date_picker", "start_date"),
    Output("date_picker", "end_date"),
    Input("jump_to_present_btn", "n_clicks")
)
def jump_to_present(button_press):
    return date(2023, 4, 7), date(2023, 4, 14)

@app.callback(
    Output("last_updated_timer", "children"),
    Input("dataframe_picker", "value"))

def update_df_picker (picker):
    return html.Span(f'{picker}')

if __name__ == '__main__':
    app.run_server(debug=True)

Did you try to add prevent_initial_callback=True in your callback with dataframe_picker?

Yep, just tried that and I still get the error. It doesn’t seem to affect the functionality of the app. Is there any reason why this could be happening?

Hello @winstonchiong,

What if you changed the dataframe_picker to be a dcc.Store and set a default, then have your other page designed to update the store based upon selection.

That way the value should always exist inside the app, because it is being triggered before your page layout completely loads. (This is done as a post request after the initial page load)

I could try that! That seems like a complicated workaround to a simple problem; I simply have a dropdown ID in another tab that isn’t present in app.py when it initially loads.

Also, should callbacks live in app.py or in the file of the page? Currently, I have all the callbacks live in app.py because they share the same data querying functions.

Also this only happens when I start the app in a page other than alltime.py. For some reason when I start the app in alltime.py I don’t get the Input error despite the ID belonging to today.py not appearing in the initial layout.

I’m so confused right now; I do indeed have callbacks in ``app.py``` that reference non-present Inputs and Outputs (such as when I am in the homepage), but isn’t Dash supposed to validate all the HTML id’s?

My Dash app also appears to be reloading my graphs when switch between pages. Is this normal behavior?