<h2 dir="auto">Summary</h2>
<p dir="auto">Trying to register a custom 404 (or any?) error handler using blueprints and the declaritive style seems to have no effect:</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="# Has no effect
@blueprint.errorhandler(404)
def ...

# Yet this works:
@app.errorhandler(404)
def ..."><pre class="notranslate"><span class="pl-c"># Has no effect</span>
<span class="pl-en">@<span class="pl-s1">blueprint</span>.<span class="pl-en">errorhandler</span>(<span class="pl-c1">404</span>)</span>
<span class="pl-k">def</span> ...

<span class="pl-c"># Yet this works:</span>
<span class="pl-en">@<span class="pl-s1">app</span>.<span class="pl-en">errorhandler</span>(<span class="pl-c1">404</span>)</span>
<span class="pl-k">def</span> ...</pre></div>
<p dir="auto">Of course, the blueprint wouldn't work if it wasn't registered, but I have registered it and yet, the custom error page isn't shown. Here are two <strong>files</strong> you can use to reproduce the lack of custom error handling:</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="# FILE: app.py
import flask
import views

app = flask.Flask(__name__)
app.register_blueprint(views.blueprint)
app.run()"><pre class="notranslate"><span class="pl-c"># FILE: app.py</span>
<span class="pl-k">import</span> <span class="pl-s1">flask</span>
<span class="pl-k">import</span> <span class="pl-s1">views</span>

<span class="pl-s1">app</span> <span class="pl-c1">=</span> <span class="pl-s1">flask</span>.<span class="pl-v">Flask</span>(<span class="pl-s1">__name__</span>)
<span class="pl-s1">app</span>.<span class="pl-en">register_blueprint</span>(<span class="pl-s1">views</span>.<span class="pl-s1">blueprint</span>)
<span class="pl-s1">app</span>.<span class="pl-en">run</span>()</pre></div>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="# FILE: views.py
import flask
blueprint = flask.Blueprint('views', __name__, template_folder='templates')

@blueprint.route('/')
def index():
    return &quot;Hello world, I might have errors!&quot;

@blueprint.errorhandler(404)
def errors_404(e):
    return &quot;I am a 404!&quot;, 404"><pre class="notranslate"><span class="pl-c"># FILE: views.py</span>
<span class="pl-k">import</span> <span class="pl-s1">flask</span>
<span class="pl-s1">blueprint</span> <span class="pl-c1">=</span> <span class="pl-s1">flask</span>.<span class="pl-v">Blueprint</span>(<span class="pl-s">'views'</span>, <span class="pl-s1">__name__</span>, <span class="pl-s1">template_folder</span><span class="pl-c1">=</span><span class="pl-s">'templates'</span>)

<span class="pl-en">@<span class="pl-s1">blueprint</span>.<span class="pl-en">route</span>(<span class="pl-s">'/'</span>)</span>
<span class="pl-k">def</span> <span class="pl-en">index</span>():
    <span class="pl-k">return</span> <span class="pl-s">"Hello world, I might have errors!"</span>

<span class="pl-en">@<span class="pl-s1">blueprint</span>.<span class="pl-en">errorhandler</span>(<span class="pl-c1">404</span>)</span>
<span class="pl-k">def</span> <span class="pl-en">errors_404</span>(<span class="pl-s1">e</span>):
    <span class="pl-k">return</span> <span class="pl-s">"I am a 404!"</span>, <span class="pl-c1">404</span></pre></div>
<h3 dir="auto">Expected Behavior</h3>
<p dir="auto">We should see the response "I am a 404!" for <a href="http://127.0.0.1:5000/abc" rel="nofollow">http://127.0.0.1:5000/abc</a></p>
<h3 dir="auto">Actual Behavior</h3>
<p dir="auto">We see Flask's standard error page:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="Not Found

The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again."><pre class="notranslate"><code class="notranslate">Not Found

The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.
</code></pre></div>
<h3 dir="auto">Working if changed to app.errorhandler()</h3>
<p dir="auto">It seems like I have the setup correct (I hope I'm not wasting your time!) because with a slight move from <code class="notranslate">blueprint.errorhandler()</code> to <code class="notranslate">app.errorhandler()</code>, the expected behavior is achieved:</p>
<h4 dir="auto">This one works</h4>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="# FILE: app.py
import flask
import views

app = flask.Flask(__name__)
app.register_blueprint(views.blueprint)

# I just moved this from views.py and changed blueprint to app
# Of course, the error report is that this shouldn't be necessary.
@app.errorhandler(404)
def errors_404(e):
    return &quot;I am a 404!&quot;, 404

app.run()"><pre class="notranslate"><span class="pl-c"># FILE: app.py</span>
<span class="pl-k">import</span> <span class="pl-s1">flask</span>
<span class="pl-k">import</span> <span class="pl-s1">views</span>

<span class="pl-s1">app</span> <span class="pl-c1">=</span> <span class="pl-s1">flask</span>.<span class="pl-v">Flask</span>(<span class="pl-s1">__name__</span>)
<span class="pl-s1">app</span>.<span class="pl-en">register_blueprint</span>(<span class="pl-s1">views</span>.<span class="pl-s1">blueprint</span>)

<span class="pl-c"># I just moved this from views.py and changed blueprint to app</span>
<span class="pl-c"># Of course, the error report is that this shouldn't be necessary.</span>
<span class="pl-en">@<span class="pl-s1">app</span>.<span class="pl-en">errorhandler</span>(<span class="pl-c1">404</span>)</span>
<span class="pl-k">def</span> <span class="pl-en">errors_404</span>(<span class="pl-s1">e</span>):
    <span class="pl-k">return</span> <span class="pl-s">"I am a 404!"</span>, <span class="pl-c1">404</span>

<span class="pl-s1">app</span>.<span class="pl-en">run</span>()</pre></div>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="# FILE: views.py
import flask
blueprint = flask.Blueprint('views', __name__, template_folder='templates')

@blueprint.route('/')
def index():
    return &quot;Hello world, I might have errors!&quot;"><pre class="notranslate"><span class="pl-c"># FILE: views.py</span>
<span class="pl-k">import</span> <span class="pl-s1">flask</span>
<span class="pl-s1">blueprint</span> <span class="pl-c1">=</span> <span class="pl-s1">flask</span>.<span class="pl-v">Blueprint</span>(<span class="pl-s">'views'</span>, <span class="pl-s1">__name__</span>, <span class="pl-s1">template_folder</span><span class="pl-c1">=</span><span class="pl-s">'templates'</span>)

<span class="pl-en">@<span class="pl-s1">blueprint</span>.<span class="pl-en">route</span>(<span class="pl-s">'/'</span>)</span>
<span class="pl-k">def</span> <span class="pl-en">index</span>():
    <span class="pl-k">return</span> <span class="pl-s">"Hello world, I might have errors!"</span></pre></div>
<h3 dir="auto">Environment</h3>
<ul dir="auto">
<li>Python version: 3.8</li>
<li>Flask version: 1.1.2</li>
<li>Werkzeug version: 1.0.1</li>
<li>OS: macOS Catalina</li>
</ul>
<p dir="auto">Sorry in advance if it is not the right place to open this kind of issue.<br>
I think it would be nice to have issues labelled 'good first bug' for people wanting to contribute but not knowing how to start.</p>