dcc.Graph figure error

Does anyone know what this error means?

Traceback (most recent call last):
  File "Dash_File.py", line 857, in <module>
    figure= callback_func(n_clicks=0, value="Spikes"),
  File "C:\Users\kayvo\anaconda3\lib\site-packages\dash\dash.py", line 1006, in add_context
    output_spec = kwargs.pop("outputs_list")
KeyError: 'outputs_list'

They are giving me an error for this:

dcc.Graph(
    id='Concrete_Health_method',
    figure= callback_func(n_clicks=0, value="Spikes"),
    #calculator_1.graph_concrete(df2)
    style ={'display': 'inline-block'})
    ])

The figure specifically

I don’t know what is wrong with having it defined like that

If anyone wants to see my callback_func, then here it is:

#Callback for submitting everything.
@app.callback(Output('target', 'children'), Input('submit', 'n_clicks'), Input('Categories', 'value'))
def callback_func(n_clicks, value):
    if (n_clicks != 0):
        if os.path.exists(UPLOAD_DIRECTORY):
            for file in uploaded_files():
                dfs = pd.read_excel(file, sheet_name=value)
                # Define if we analyzing Premium or Cut Spikes
                # Define if the data is reliable 
                #Calculation data below to display graph

Which version of Dash are you using? If it’s old (current is 1.21.0), try again after updating.

Edit:
Ah, I see the problem. Simply calling callback_func directly from the code as you do here:
figure= callback_func(n_clicks=0, value="Spikes"),
will not work because callback_func is decorated as @app.callback. If you want the function’s output to go in the figure, why not use Output('Concrete_Health_method', 'figure')?

Another workaround that should work is to isolate what the function does in another function and then call that from the callback like so:

@app.callback(...)
def callback_func(n_clicks, value):
   return actual_func(n_clicks, value)

def actual_func(n_clicks, value):
   # the actual computation ...
   return return_value

Note how actual_func is not decorated, so you could call it from anywhere in the code.

Oh, good idea. However, what would I pass into my figure? I need to pass the function in there?

Btw, I am in a dilemma here. Here is my code here when we were talking about the function of the app.callback I was using to pass into my figure for my graph since it calculates it:

#Callback for submitting everything.
@app.callback(Output('target', 'children'), Input('submit', 'n_clicks'), Input('Categories', 'value'))
def callback(n_clicks, value):
    if (n_clicks != 0):
        if os.path.exists(UPLOAD_DIRECTORY):
            for file in uploaded_files():
                dfs = pd.read_excel(file, sheet_name=value)

As you can see- Please look at the dfs = pd.read_excel(file, sheet_name=value) line.

How would I be able to take the code below it which is contingent upon the dfs and make it into a new and separate function if my sheet_name is contingent upon the input(value) which needs to be defined and passed in to read the users choice for the dropdown?

I need your help. I am stuck in this predicament with no way to escape.

It’ll be hard to help help without seeing the complete code. Try building a very simple example of what you are trying to do, post the complete code and the issues there are.

If your chosen sheetname is dependent on the input value, you can just pass that value into the next function, as shown in the short example I posted above. value is an input to callback_func and then passed on to actual_func, where it can be used. Am I misunderstanding the problem here?

Oh, no. You are right. However, I need a figure =
in order for the graph to show. However, I can’t use that as you mentioned that passing n_clicks and value would be predefining them as the value is what the user inputs, however, I need to predefine it to use it. Plus, that won’t work as that will give me an error. I don’t know how to solve this dilemma.

@app.callback(dash.dependencies.Output('Categories', 'value'),[dash.dependencies.Input('Categories', 'options')])
def update_output_dropdown(value):
    return 'You have selected "{}"'.format(value)




        

#Callback for submitting everything.
@app.callback(Output('target', 'children'), Input('submit', 'n_clicks'), Input('Categories', 'value'))
def callback(n_clicks, value):
    if (n_clicks != 0):
         return calculation(n_clicks, value)

ctx = dash.callback_context
def calculation(n_clicks,value):
    if ctx.triggered:
        if os.path.exists(UPLOAD_DIRECTORY):
            for file in uploaded_files():
                dfs = pd.read_excel(file, sheet_name=value)
app.layout = html.Div(
    children=[
    html.H1(children='RailTec Dashboard'),
    #Uploading the files to the board. We want to make sure that two files can be uploaded, read, and grab the same categories to the direct coorelated category.
    #For choosing files between tabs
    html.Div(
    [
        html.H2("Upload"),
        dcc.Upload(
            id="upload-data",
            children=html.Div(
                ["Drag and drop or click to select a file to upload."]
            ),
            style={
                "width": "100%",
                "height": "60px",
                "lineHeight": "60px",
                "borderWidth": "1px",
                "borderStyle": "dashed",
                "borderRadius": "5px",
                "textAlign": "center",
                "margin": "10px",
            },
            multiple=True,
        ),
        html.H2("File List"),
        html.Ul(id="file-list"),
    ],
    style={"maxWidth": "500px"},
    ),
    
    #Drop Down Menu for the categories. 
    dcc.Dropdown(
        id = 'Categories',
        options=[
            {'label': 'Spikes', 'value': 'Spikes'},
            {'label': 'Fasteners', 'value': 'Fasteners'},
            {'label': 'Ballast Level', 'value': 'Ballast Level'},
            {'label': 'Spikes Med', 'value': 'Spikes'},
            {'label': 'Fasteners Med', 'value': 'Fasteners'},
            {'label': 'Ballast Level Med', 'value': 'Ballast Level'},
            {'label': 'Spikes Bad', 'value': 'Spikes'},
            {'label': 'Fasteners Bad', 'value': 'Fasteners'},
            {'label': 'Ballast Level Bad', 'value': 'Ballast Level'}
        ],
        placeholder="Select a category",
        value = "Spikes"
    ),
    #html.Div(id='dd-output-container', children = []),

    html.Form([
    #Enter button Event to trigger app callback for dropdown and upload data to submit what to calculate.
    html.Div(id='target'),
    html.Button('Submit',id='submit', n_clicks=0),
    ]),
    
 
    dcc.Graph(
    id='calculation(n_clicks,value)',
    figure = calculation(), # I don't know how to solve this dilemma
    #calculator_1.graph_concrete(df2)
    style ={'display': 'inline-block'})
    ])

I hope this doesn’t offend, but I believe you are lacking in some basic understanding of Dash, as there are many queer or unusual parts in your code, which also appears to be incomplete (UPLOAD_DIRECTORY is defined nowhere, for example). This is why I recommended building a very simple example first. A look at the Basic Callbacks chapter of the tutorial will help, too.

Regarding your dilemma in particual:

    dcc.Graph(
    id='calculation(n_clicks,value)',
    figure = calculation(), # I don't know how to solve this dilemma
    #calculator_1.graph_concrete(df2)
    style ={'display': 'inline-block'})

First off, the id is unusual. You don’t put the function call here, but the “name” of the graph, e.g. my-graph for a simple example. You can then set that as output to your callback, so instead of

@app.callback(Output('target', 'children'), Input('submit', 'n_clicks'), Input('Categories', 'value'))
def callback(n_clicks, value):

you would have (note that the first argument to @app.callback changed)

@app.callback(Output('my-graph', 'figure'), Input('submit', 'n_clicks'), Input('Categories', 'value'))
def callback(n_clicks, value):

You then also don’t need to set the figure explicitly in the dcc.Graph definition, because it will get set when the callback runs initially (and that’s the way it should be done, as I first suggested in my initial reply).

But again, I recommend building a simple example first, or take one from the tutorial and play around with it to understand how callbacks and their outputs really work.

1 Like

I apologize. I left a couple things out. I ran into a new problem and adopted the code pieces I was missing.

UPLOAD_DIRECTORY = "Dash_Folder"
#Callback for dropdown menu
@app.callback(dash.dependencies.Output('Categories', 'value'),[dash.dependencies.Input('Categories', 'options')])
def update_output_dropdown(value):
    return 'You have selected "{}"'.format(value)




        

#Callback for submitting everything.
@app.callback(Output('graph', 'figure'), Input('graph-with-button', 'n_clicks'), Input('Categories', 'value'))
def callback(n_clicks, value):
    if (n_clicks != 0):
         return calculation(n_clicks, value)

ctx = dash.callback_context
def calculation(n_clicks,value):
        if os.path.exists(UPLOAD_DIRECTORY):
            for file in uploaded_files():
                dfs = pd.read_excel(file, sheet_name=value)
                if  value == 'Spikes (Oct 23)':
                    # Define if we analyzing Premium or Cut Spikes
                    # Define if the data is reliable 
                    #Code here
app.layout = html.Div(
    children=[
 #Drop Down Menu for the categories. 
    dcc.Dropdown(
        id = 'Categories',
        options=[
            {'label': 'Spikes (Oct 23)', 'value': 'Spikes'},
            {'label': 'Fasteners', 'value': 'Fasteners'},
            {'label': 'Ballast Level', 'value': 'Ballast Level'},
            {'label': 'Spikes Med', 'value': 'Spikes'},
            {'label': 'Fasteners Med', 'value': 'Fasteners'},
            {'label': 'Ballast Level Med', 'value': 'Ballast Level'},
            {'label': 'Spikes Bad', 'value': 'Spikes'},
            {'label': 'Fasteners Bad', 'value': 'Fasteners'},
            {'label': 'Ballast Level Bad', 'value': 'Ballast Level'}
        ],
        placeholder="Select a category",
        value = "Spikes"
    ),
    #html.Div(id='dd-output-container', children = []),

    html.Form([
    #Enter button Event to trigger app callback for dropdown and upload data to submit what to calculate.
    html.Div(id='graph-with-button'),
    html.Button('Submit',id='submit', n_clicks=0),
    ]),
    

    dcc.Graph(
    id = 'graph'
    ), 
    
    ])
However, I get an error that says: Cannot read property 'layout' of null
Here is the Traceback. Warning that it is just pure gibberish. 

(This error originated from the built-in JavaScript code that runs Dash apps. Click to see the full stack trace or open your browser’s console.)
TypeError: Cannot read property ‘layout’ of null

at t.value (http://127.0.0.1:8050/_dash-component-suites/dash_core_components/async-graph.v1_16_0m1617903285.js:1:12380)

at t.value (http://127.0.0.1:8050/_dash-component-suites/dash_core_components/async-graph.v1_16_0m1617903285.js:1:16413)

at callComponentWillReceiveProps (http://127.0.0.1:8050/_dash-component-suites/dash_renderer/react-dom@16.v1_9_1m1624988823.14.0.js:13111:16)

at updateClassInstance (http://127.0.0.1:8050/_dash-component-suites/dash_renderer/react-dom@16.v1_9_1m1624988823.14.0.js:13313:9)

at updateClassComponent (http://127.0.0.1:8050/_dash-component-suites/dash_renderer/react-dom@16.v1_9_1m1624988823.14.0.js:17242:22)

at beginWork (http://127.0.0.1:8050/_dash-component-suites/dash_renderer/react-dom@16.v1_9_1m1624988823.14.0.js:18755:18)

at HTMLUnknownElement.callCallback (http://127.0.0.1:8050/_dash-component-suites/dash_renderer/react-dom@16.v1_9_1m1624988823.14.0.js:182:16)

at Object.invokeGuardedCallbackDev (http://127.0.0.1:8050/_dash-component-suites/dash_renderer/react-dom@16.v1_9_1m1624988823.14.0.js:231:18)

at invokeGuardedCallback (http://127.0.0.1:8050/_dash-component-suites/dash_renderer/react-dom@16.v1_9_1m1624988823.14.0.js:286:33)

at beginWork$1 (http://127.0.0.1:8050/_dash-component-suites/dash_renderer/react-dom@16.v1_9_1m1624988823.14.0.js:23338:9)

I can’t tell for sure what is the problem. Maybe I could if you posted a reproducible example.

One thing to look out for is that you don’t want your callback to return nothing at all. E.g. if n_clicks is 0 you cannot simply return nothing, but have to return dash.no_update or an empty figure.

Oh, wait, for my callback? what do you recommend I return then instead of n_clicks?

Is this valid to do?

def calculation(n_clicks,value):
    if n_clicks != 0:
        if os.path.exists(UPLOAD_DIRECTORY):
            for file in uploaded_files():
                dfs = pd.read_excel(file, sheet_name=value)
                if  value == 'Spikes (Oct 23)':
                    # Define if we analyzing Premium or Cut Spikes
                    # Define if the data is reliable 
                    #code here
                    def Health_Graph(DF):
                        ax_DF = px.line(DF, x = 'Stationing', y = 'Health', title= 'Fastener Health Index')
                        return ax_DF 
                    Health_Graph(DF)
                    fig = Health_Graph(DF)
                    return fig```

The problem is if your callback doesn’t return anything. Currently, from what I’ve seen, the callback logic is like this:

@app.callback(Output('graph', 'figure'), Input('graph-with-button', 'n_clicks'), Input('Categories', 'value'))
def callback(n_clicks, value):
    if (n_clicks != 0):
         # return the figure
     # nothing is returned if n_clicks == 0!

And not returning anything when n_clicks==0 seems to be the problem here. At least, if I try that in a minimal example, I get the exact same error as you (Cannot read property ‘layout’ of null).

See if this works:

@app.callback(Output('graph', 'figure'), Input('graph-with-button', 'n_clicks'), Input('Categories', 'value'))
def callback(n_clicks, value):
    if (n_clicks != 0):
         return calculation(n_clicks, value)
    else:
         return dash.no_update

Unfortunately, I still get the same error. Here is my code so far.

UPLOAD_DIRECTORY = "Dash_Folder"
#Callback for dropdown menu
@app.callback(dash.dependencies.Output('Categories', 'value'),[dash.dependencies.Input('Categories', 'options')])
def update_output_dropdown(value):
    return 'You have selected "{}"'.format(value)




        

#Callback for submitting everything.
@app.callback(Output('graph', 'figure'), Input('graph-with-button', 'n_clicks'), Input('Categories', 'value'))
def callback(n_clicks, value):
    if (n_clicks != 0):
         return calculation(n_clicks, value)
    else:
        return dash.no_update

ctx = dash.callback_context
def calculation(n_clicks,value):
    if n_clicks != 0:
        if os.path.exists(UPLOAD_DIRECTORY):
            for file in uploaded_files():
                dfs = pd.read_excel(file, sheet_name=value)
                if  value == 'Spikes (Oct 23)':
                    # Define if we analyzing Premium or Cut Spikes
                    # Define if the data is reliable 
                     #Code for calculations 
                     def Health_Graph(DF):
                        return px.line(DF, x = 'Stationing', y = 'Health', title= 'Fastener Health Index') 
                    Health_Graph(DF)

app.layout = html.Div(
    children=[
     #Drop Down Menu for the categories. 
    dcc.Dropdown(
        id = 'Categories',
        options=[
            {'label': 'Spikes', 'value': 'Spikes (Oct 23)'},
            {'label': 'Fasteners', 'value': 'Fasteners (Oct 23)'},
            {'label': 'Ballast Level', 'value': 'Ballast Level (Oct 23)'},
            {'label': 'Spikes', 'value': 'Spikes (Oct 23) Med'},
            {'label': 'Fasteners', 'value': 'Fasteners (Oct 23) Med'},
            {'label': 'Ballast', 'value': 'Ballast Level (Oct 23) Med'},
            {'label': 'Spikes', 'value': 'Spikes (Oct 23) Bad'},
            {'label': 'Fasteners', 'value': 'Fasteners (Oct 23) Bad'},
            {'label': 'Ballast Level', 'value': 'Ballast Level (Oct 23) Bad'}
        ],
        placeholder="Select a category",
        value = "Fasteners (Oct 23)"
    ),
    #html.Div(id='dd-output-container', children = []),

    html.Form([
    #Enter button Event to trigger app callback for dropdown and upload data to submit what to calculate.
    html.Div(id='graph-with-button'),
    html.Button('Submit',id='submit', n_clicks=0),
    ]),
    

    dcc.Graph(
    id = 'graph'
    ), 
    
    ])

I don’t know what else I am doing wrong. Everything else seems perfect.

Oh, I did the dash.no_update for my function which had n_clicks != 0.
However, I am now faced with a frozen Dash app no matter what I do.