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 blueprint '{self.name}'. It has already been registered at least once, any changes will not be applied consistently.
Make sure all imports, decorators, functions, etc. needed to set up the blueprint are done before registering it. What it means
Like the app guard, a Blueprint sets _got_registered_once=True once it has been registered on any app. Blueprint setup methods (@setupmethod on the blueprint: route, add_url_rule, before_request, errorhandler, etc.) call _check_setup_finished and raise AssertionError if called after the first registration, because deferred functions are replayed only at registration time.
Solutions
- Define all routes/handlers on the blueprint BEFORE calling app.register_blueprint(bp).
- Use a fresh blueprint instance per registration if you must mutate it (factory function returning a new Blueprint).
- For shared extension behavior, register additional blueprints rather than mutating an already-registered one.
Example fix
// before
app.register_blueprint(bp)
@bp.route('/late') # raises
def late(): ...
// after
@bp.route('/late')
def late(): ...
app.register_blueprint(bp) Defensive patterns
Strategy: validation
Validate before calling
def assert_bp_settable(bp):
if getattr(bp, '_got_registered_once', False):
raise RuntimeError(f'blueprint {bp.name!r} already registered; configure before register_blueprint')
Type guard
def is_bp_setup_open(bp) -> bool:
return not getattr(bp, '_got_registered_once', False)
Try / catch
try:
bp.add_url_rule('/x', view_func=fn)
except AssertionError as e:
if 'blueprint' in str(e) and 'no longer be called' in str(e):
# use a fresh blueprint instance and retry
raise Prevention
- Define all blueprint routes/handlers before register_blueprint.
- Use a blueprint factory to get a fresh instance if you must rebuild.
- Do not extend a blueprint from another module after it has been mounted.
When it happens
Trigger: Registering the blueprint with app.register_blueprint(bp) and then calling bp.route(...)/bp.add_url_rule(...)/bp.errorhandler(...)/bp.before_app_request(...) afterwards; defining routes in a module imported lazily after registration.
Common situations: Plugin packages that register a blueprint then extend it; circular imports causing blueprint mutation after registration; tests that reuse one blueprint instance across multiple test app registrations and try to add routes between.
Related errors
- The setup method ' ' can no longer be called on the…
- 'name' may not be empty.
- 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…
AI-assisted analysis of pallets/flask@3596b1ab61 (2026-08-11).
Data as JSON: /api/errors/3aee6862ff7e028c.
Report an issue: GitHub.
Appendix: source
Thrown at src/flask/sansio/blueprints.py:215
if "." in name:
raise ValueError("'name' may not contain a dot '.' character.")
self.name = name
self.url_prefix = url_prefix
self.subdomain = subdomain
self.deferred_functions: list[DeferredSetupFunction] = []
if url_defaults is None:
url_defaults = {}
self.url_values_defaults = url_defaults
self.cli_group = cli_group
self._blueprints: list[tuple[Blueprint, dict[str, t.Any]]] = []
def _check_setup_finished(self, f_name: str) -> None:
if self._got_registered_once:
raise AssertionError(
f"The setup method '{f_name}' can no longer be called on the blueprint"
f" '{self.name}'. It has already been registered at least once, any"
" changes will not be applied consistently.\n"
"Make sure all imports, decorators, functions, etc. needed to set up"
" the blueprint are done before registering it."
)
@setupmethod
def record(self, func: DeferredSetupFunction) -> None:
"""Registers a function that is called when the blueprint is
registered on the application. This function is called with the
state as argument as returned by the :meth:`make_setup_state`
method.
"""
self.deferred_functions.append(func)
@setupmethod
def record_once(self, func: DeferredSetupFunction) -> None:View on GitHub (pinned to 3596b1ab61)