pallets/flask · error · AssertionError
The setup method '{f_name}' can no longer be called on the b
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
An AssertionError from `Blueprint._check_setup_finished` (src/flask/sansio/blueprints.py:213-221), the blueprint counterpart of the app-level setup freeze. Every `@setupmethod` on a blueprint (route, before_request, errorhandler, record, register_blueprint, ...) checks `_got_registered_once`; once the blueprint has been registered on an application, its deferred setup functions have already been replayed onto that app, so later additions would exist on some registrations and not others. Flask 2.3 made this a hard error.
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 6a2f545bfd)
Solutions
- Move `app.register_blueprint(bp)` after all of the blueprint's routes and handlers are defined — typically registration lives in `create_app()`, which imports the fully-built blueprint module.
- In tests, build a fresh app (and fresh blueprints if they're created dynamically) per test rather than re-decorating shared module-level blueprints.
- If routes are added conditionally, decide them before registration (feature flags evaluated in the blueprint module), not afterward.
Example fix
# before
bp = Blueprint("admin", __name__)
app.register_blueprint(bp)
@bp.route("/users") # AssertionError: already registered
def users(): ...
# after
bp = Blueprint("admin", __name__)
@bp.route("/users")
def users(): ...
app.register_blueprint(bp) Defensive patterns
Strategy: validation
Validate before calling
if bp._got_registered_once:
raise RuntimeError('Blueprint already registered; define routes before app.register_blueprint')
bp.route('/x')(view) Type guard
def can_modify_blueprint(bp):
return not getattr(bp, '_got_registered_once', False) Try / catch
try:
bp.before_request(hook)
except AssertionError:
log.error('Blueprint %s already registered; move setup before register_blueprint', bp.name) Prevention
- Define all blueprint routes/hooks at module level, then register the blueprint last in the app factory
- Never add routes to a blueprint after app.register_blueprint has been called on it
- Avoid conditional/lazy route registration inside request handling
When it happens
Trigger: Calling `@bp.route`, `bp.before_request`, `bp.errorhandler`, etc. after `app.register_blueprint(bp)` has run for that blueprint object. Classic shapes: registering the blueprint at the top of a module and defining routes below it; a factory that registers a shared module-level blueprint, then a test or second factory call tries to add more routes; conditionally importing a routes module only after registration.
Common situations: Import-order mistakes where `create_app()` registers the blueprint before the module defining its routes is fully imported; tests mutating a module-level blueprint that a previous test's app already registered; plugin architectures adding routes to an already-mounted blueprint; Flask <2.3 code that silently tolerated this now failing after upgrade.
Related errors
- The setup method '{f_name}' can no longer be called on the a
- 'name' may not be empty.
- 'name' may not contain a dot '.' character.
- Cannot register a blueprint on itself
- The name '{self_name}' is already registered for {bp_desc} b
AI-assisted analysis of pallets/flask@6a2f545bfd (2026-07-31).
Data as JSON: /data/errors/3aee6862ff7e028c.json.
Report an issue: GitHub ↗.