Why does dash return a status code of 200 when a page is not found

I trying to set up a 404.html page template but the issue that I am running into is that dash returns a 200 when a request is made to a page that does not exist. Why is that?

Request URL: http://127.0.0.1:8050/test
Request Method: GET
Status Code: 200 OK

Example:

app.py

from dash import Dash, html, page_container
from flask import render_template

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

app.layout = html.Div([
    page_container
])

@app.server.errorhandler(404)
def not_found(error):
    return render_template('404.html'), 404


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

pages/home.py

import dash
from dash import html

dash.register_page(__name__, path='/')

layout = html.Div('Hello World')

404.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>404 Not Found</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            text-align: center;
            background-color: #1a1a2e;
            color: white;
            margin: 0;
            padding: 0;
        }
        h1 {
            font-size: 4em;
            margin-top: 50px;
        }
        p {
            font-size: 1.5em;
        }
        .emoji {
            font-size: 5em;
        }
        a {
            color: #ffcc00;
            text-decoration: none;
            font-weight: bold;
        }
        a:hover {
            text-decoration: underline;
        }
    </style>
</head>
<body>
    <div class="emoji">🚀👨‍🚀</div>
    <h1>404: Lost in Space</h1>
    <p>Uh-oh! The page you’re looking for has drifted into the void.</p>
    <p>Maybe it’s on another planet? Or just <i>really</i> good at hiding?</p>
    <p><a href="/">Return to Mission Control</a></p>
</body>
</html>

Hi @PyGuy !

Dash handles 404’s internally and returns a valid response with the 404 dash component layout. If you haven’t set a not_found_404.py file dash is going to render a basic Title.

Just create the mentioned file and ad the styles from the html to a css file in your assets and you are good to go.

Thank you for the response but that option only inserts a layout when there is a “404” into dash.page_container and keeps the default layout. I really just want to return a static html file. I will probably end up going with something like

@app.server.before_request
def override_dash_404():
    """ Ensure unknown paths return a proper 404 page. """

    # Store the stripped request path once
    requested_path = flask.request.path.strip("/")

    # Known Dash and Flask routes
    dash_routes = {page["path"].strip("/") for page in dash.page_registry.values()}
    flask_routes = {rule.rule.strip("/") for rule in app.server.url_map.iter_rules()}

    # ✅ Allow valid Dash routes
    if requested_path in dash_routes:
        return  # Let Dash handle it

    # ✅ Allow valid Flask routes
    if requested_path in flask_routes:
        return  # Let Flask handle it

    # ✅ Allow Dash-internal API calls (updates, assets, favicon, etc.)
    if flask.request.path.startswith(("/_dash", "/assets/", "/favicon.ico")):
        return  # Let Dash handle it

    # ❌ Everything else gets a real 404 error
    flask.abort(404)  # This ensures Flask's real 404 handling takes over

@app.server.errorhandler(404)
def page_not_found(error):
    """ Serve a proper 404 page instead of Dash's fake 404 """
    return flask.render_template("404.html"), 404

Yes, that’s the solution then

Hello @PyGuy,

That will work, though I’m not sure how it will play with templates for the dash pages. You can make special cases for that however.