NoLayoutException on deployment of multi page dash app example code

Hello,

New to the forum. Love dash, but running into a multi-page deployment issue.

I am trying to recreate and deploy the sample multipage app from the user guide, deploying with Gunicorn+Nginx, but I run into the error below (actually ran into similar error on a apache+mod_wsgi deployment as well):

Aug 06 16:02:21 GunicornNginxFlask gunicorn[4415]: Traceback (most recent call last):
Aug 06 16:02:21 GunicornNginxFlask gunicorn[4415]: File “/home/andrew/myproject/myprojectenv/lib/python3.6/site-packages/flask/app.py”, line 2292, in wsgi_app
Aug 06 16:02:21 GunicornNginxFlask gunicorn[4415]: response = self.full_dispatch_request()
Aug 06 16:02:21 GunicornNginxFlask gunicorn[4415]: File “/home/andrew/myproject/myprojectenv/lib/python3.6/site-packages/flask/app.py”, line 1808, in full_dispatch_re
Aug 06 16:02:21 GunicornNginxFlask gunicorn[4415]: self.try_trigger_before_first_request_functions()
Aug 06 16:02:21 GunicornNginxFlask gunicorn[4415]: File “/home/andrew/myproject/myprojectenv/lib/python3.6/site-packages/flask/app.py”, line 1855, in try_trigger_befo
Aug 06 16:02:21 GunicornNginxFlask gunicorn[4415]: func()
Aug 06 16:02:21 GunicornNginxFlask gunicorn[4415]: File “/home/andrew/myproject/myprojectenv/lib/python3.6/site-packages/dash/dash.py”, line 715, in _setup_server
Aug 06 16:02:21 GunicornNginxFlask gunicorn[4415]: ‘’
Aug 06 16:02:21 GunicornNginxFlask gunicorn[4415]: dash.exceptions.NoLayoutException: The layout was None at the time that run_server was called.

my wsgi file content is

from app import server as application
application.secret_key = ‘fj829082f84j29f8asdfj3298jfaksdnkdsnj’

my Systemd file is:

[Unit]
Description=Gunicorn instance to serve myproject
After=network.target

[Service]
User=andrew
Group=www-data
WorkingDirectory=/home/andrew/myprojectenv
Environment=“PATH=/home/andrew/myproject/myprojectenv/bin”
ExecStart=/home/andrew/myproject/myprojectenv/bin/gunicorn --workers 3 --bind unix:/home/andrew/myproject/myproject.sock -m 007 wsgi:application

[Install]
WantedBy=multi-user.target

and my Nginx goes to the correct socket:


proxy_pass http://unix:/home/andrew/myproject/myproject.sock;
}

The rest of the dash files come directly from the examples, with the same file structure:

  • app.py
  • index.py
  • apps
    |-- init.py
    |-- app1.py
    |-- app2.py

I can get the multipage app to work when it’s all within the same file (the page1/page2 example), but with the separate folders it becomes an issue

Does anyone know where or how I should begin troubleshooting this? I’ve looked at all the different parts (gunicorn, nginx, systemd, example code, etc…) and the relevant community posts and am stumped.

Any help appreciated, and thank you!

1 Like

I had the same issue and in the end I fixed it by changing index.py by adding this line:

from app import server

And then I switched the Procfile to this:

web: gunicorn index:server

I’m having the same issue. I’m running an application that I wrote on a windows 10 box.

What does the error mean and how do you fix it?

This issue is caused by the module that sets the layout of your Dash instance not being imported.

You need to make sure that the module you point your WSGI server (which contains the Flask server instance) at also sets the Dash layout or imports the module that sets the layout.

For example, given the project layout under the section “Structuring a Multi-Page App” within the Dash Docs you could try to point your WSGI server at the Flask instance attached to the Dash instance in app.py (ie app.app:server). This would fail because the app module does not set the layout nor does it import the module that does. Instead you would point your WSGI server at index.app:server.

2 Likes

I’m having the same issue and the layout for multi-page app from the docs, as you point out if I point the WSGIs-server(gunicorn) to app:server I get no layout exception, when pointing it to index:server or index.app:server or index:app.server then nothing at all happens.

If I restructure the content within the files a bit, so move the app.layout from index.py to app.py and point gunicorn to app:server then it works BUT only static content no dynamic content renders.

this is driving me nuts!

Any suggestions?

Pointing your WSGI server at index:app.server should work, and I just tested it myself to confirm. When you say “nothing at all happens”, can you be more specific?

Is there no terminal output, or nothing happen when you navigate to a page in the browser?

You should be able to visit http://localhost:8000/apps/app1 in your browser. (Adjusting for the right port/host values)

“nothing at all happens” I guess it was stuck in a loading loop of some kind, I tried waitress WSGI-server and then is worked, so I swapped and am a happy camper now!

thx

1 Like

In case others stumble upon this and are confused - @nedned I think you accidentally posted two different solutions above and one has a misplaced period and semicolon.

:white_check_mark: index:app.server worked for me .

:no_entry_sign: index.app:server did not work and returned ModuleNotFoundError.

In full, for multi-page apps following the tutorial example structure:

gunicorn index:app.server
2 Likes

Oops, good catch!

Unfortunately, I can’t edit the post as it’s been too long since posting it.

Thank you! This works!

Hi @nedned. I am running into the same issue. I followed your proposed solution and update procfile with the following to point WSGI server:

gunicorn index:app.server

Here’s my index.py if you have any suggestions/ideas on what might be going on.

server = flask.Flask(__name__)
app = dash.Dash(__name__)
app.config.suppress_callback_exceptions = True


# App Layout

app.layout = html.Div([

    # header
    html.Div([

        .
        .

        html.Div(
            html.Img(src='logo',height="100%")
            ,style={"float":"right","width":"170px","height":"100px","margin-top":"-14px"})
        ],
        className="row header"
        ),

    # tabs
    html.Div([

        dcc.Tabs(
            id="tabs",
            style={"height":"60","verticalAlign":"middle"},
            children=[
                 dcc.Tab(label="Market", value="market_tab"),
                 dcc.Tab(label="Portfolio", value="portfolio_tab"),
                 dcc.Tab(label="Reporting", value="reporting_tab"),
            ],
            value="market_tab",
        )

        ],

        className="row tabs_div"
        ),

        # Tab content
        html.Div(id="tab_content", style={"margin": "2% 3%"})

])


# In[9]:

@app.callback(Output("tab_content", "children"),
              [
                  Input("tabs", "value")
              ]
             )
def render_content(tab):
    """
    For user selections, return the relevant tab
    """
    if tab == "portfolio_tab":
        return portfolio.layout
    if tab == "reporting_tab":
        return reporting.layout
    elif tab == "market_tab":
        return market.layout
    else:
        return market.layout


# In[10]:

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

My dash multi-tab structure looks like this -


app.py
index.py
tabs
|-- tab1.py
|-- tab2.py

@here I have been following the trail here regarding the issue:

dash.exceptions.NoLayoutException: The layout was None at the time that run_server was called

I have tried everything suggested here but the problem persists. Could someone suggest something different I could try please>

The tutorial I am trying to execute is: https://towardsdatascience.com/how-to-build-a-complex-reporting-dashboard-using-dash-and-plotl-4f4257c18a7f?gi=3afc69f565fe

Hi,

I have copied the multipage example from Dash and my Dockerfile:

FROM python:3.7

# Create a working directory.
RUN mkdir wd
WORKDIR wd

# Install Python dependencies.
COPY requirements.txt .
RUN pip3 install -r requirements.txt

# Copy the rest of the codebase into the image
COPY . ./

# Finally, run gunicorn.
CMD [ "gunicorn", "--workers=5", "--threads=1", "-b 0.0.0.0:8000", "index:app.server"]

But i get the error:

 Failed to parse 'app.server' as an attribute name or function call.

Have anybody solved this?