pallets/flask · error · AssertionError
The setup method ' ' can no longer be called on the…
Error message
The setup method '{f_name}' can no longer be called on the application. It has already handled its first request, any changes will not be applied consistently.
Make sure all imports, decorators, functions, etc. needed to set up the application are done before running it. What it means
Flask marks an application with _got_first_request=True once it has handled its first request. Any method decorated with @setupmethod (route, errorhandler, before_request, context_processor, etc.) calls _check_setup_finished, which raises this AssertionError if invoked afterwards, because applying changes mid-flight would leave the app in an inconsistent state. It is a hard guard, not a warning.
Solutions
- Move all @app.route/@app.errorhandler/@app.before_request registrations and register_blueprint calls to module import time, before app.run() or before the test client issues its first request.
- If registration must be dynamic, gate it behind a flag set during startup, or use application factories that fully configure the app before it is returned/served.
- In tests, build a fresh app per test (app factory pattern) so _got_first_request resets; do configuration before the first client request.
- Search for any code path that mutates the app from inside a view, before/after handler, or background thread and hoist it out.
Example fix
// before
@app.route('/first')
def first(): return 'hi'
@app.after_request # called after first request in a test
def add_header(resp): return resp
// after - register all setup at import time, before any request
@app.route('/first')
def first(): return 'hi'
@app.after_request
def add_header(resp): return resp
# ensure app.run()/client calls happen only after all setup is imported Defensive patterns
Strategy: validation
Validate before calling
def assert_app_settable(app):
if getattr(app, '_got_first_request', False):
raise RuntimeError('app already served first request; register routes earlier')
Type guard
def is_app_setup_open(app) -> bool:
return not getattr(app, '_got_first_request', False)
Try / catch
try:
app.add_url_rule('/x', view_func=handler)
except AssertionError as e:
if 'setup method' in str(e):
# move registration to startup; do not swallow silently
raise Prevention
- Use an application factory that returns a fully-configured app before any request can happen.
- Run all route/blueprint/errorhandler registration at import time, never inside views.
- In tests, construct a fresh app per test so _got_first_request resets.
When it happens
Trigger: Calling app.route/errorhandler/before_request/teardown_request/register_blueprint/template_filter/etc. after app.run() has started serving, after a request has been dispatched (e.g. inside a view or a test that already did client.get(...)), or lazily registering routes on first import inside a request handler.
Common situations: Importing route modules lazily inside a view instead of at startup; registering blueprints triggered by the first request; running setup code in a background thread after the server started; in tests calling app.route decorators after the first client request.
Related errors
- The setup method ' ' can no longer be called on the…
- A valid Flask application was not obtained from
- 'after_this_request' can only be used when a request…
- Allowed methods must be a list of strings, for example…
- Cannot pop this context
AI-assisted analysis of pallets/flask@3596b1ab61 (2026-08-11).
Data as JSON: /api/errors/beaa8a8e3a75ed57.
Report an issue: GitHub.
Appendix: source
Thrown at src/flask/sansio/app.py:412
#: def to_python(self, value):
#: return value.split(',')
#: def to_url(self, values):
#: return ','.join(super(ListConverter, self).to_url(value)
#: for value in values)
#:
#: app = Flask(__name__)
#: app.url_map.converters['list'] = ListConverter
self.url_map = self.url_map_class(host_matching=host_matching)
self.subdomain_matching = subdomain_matching
# tracks internally if the application already handled at least one
# request.
self._got_first_request = False
def _check_setup_finished(self, f_name: str) -> None:
if self._got_first_request:
raise AssertionError(
f"The setup method '{f_name}' can no longer be called"
" on the application. It has already handled its first"
" request, any changes will not be applied"
" consistently.\n"
"Make sure all imports, decorators, functions, etc."
" needed to set up the application are done before"
" running it."
)
@cached_property
def name(self) -> str:
"""The name of the application. This is usually the import name
with the difference that it's guessed from the run file if the
import name is main. This name is used as a display name when
Flask needs the name of the application. It can be set and overridden
to change the value.
.. versionadded:: 0.8View on GitHub (pinned to 3596b1ab61)