{"id":"beaa8a8e3a75ed57","repo":"pallets/flask","slug":"the-setup-method-f-name-can-no-longer-be-calle","errorCode":null,"errorMessage":"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.\nMake sure all imports, decorators, functions, etc. needed to set up the application are done before running it.","messagePattern":"The setup method '(.+?)' can no longer be called on the application\\. It has already handled its first request, any changes will not be applied consistently\\.\nMake sure all imports, decorators, functions, etc\\. needed to set up the application are done before running it\\.","errorType":"exception","errorClass":"AssertionError","httpStatus":null,"severity":"error","filePath":"src/flask/sansio/app.py","lineNumber":412,"sourceCode":"        #:        def to_python(self, value):\n        #:            return value.split(',')\n        #:        def to_url(self, values):\n        #:            return ','.join(super(ListConverter, self).to_url(value)\n        #:                            for value in values)\n        #:\n        #:    app = Flask(__name__)\n        #:    app.url_map.converters['list'] = ListConverter\n        self.url_map = self.url_map_class(host_matching=host_matching)\n\n        self.subdomain_matching = subdomain_matching\n\n        # tracks internally if the application already handled at least one\n        # request.\n        self._got_first_request = False\n\n    def _check_setup_finished(self, f_name: str) -> None:\n        if self._got_first_request:\n            raise AssertionError(\n                f\"The setup method '{f_name}' can no longer be called\"\n                \" on the application. It has already handled its first\"\n                \" request, any changes will not be applied\"\n                \" consistently.\\n\"\n                \"Make sure all imports, decorators, functions, etc.\"\n                \" needed to set up the application are done before\"\n                \" running it.\"\n            )\n\n    @cached_property\n    def name(self) -> str:\n        \"\"\"The name of the application.  This is usually the import name\n        with the difference that it's guessed from the run file if the\n        import name is main.  This name is used as a display name when\n        Flask needs the name of the application.  It can be set and overridden\n        to change the value.\n\n        .. versionadded:: 0.8","sourceCodeStart":394,"sourceCodeEnd":430,"githubUrl":"https://github.com/pallets/flask/blob/6a2f545bfd8ed31e19066a299296917e034aca58/src/flask/sansio/app.py#L394-L430","documentation":"An AssertionError from `Flask._check_setup_finished` (src/flask/sansio/app.py:410-419), which every `@setupmethod`-decorated API calls first. Once the app has served its first request (`_got_first_request` is True), Flask freezes setup: routes, error handlers, before/after-request hooks, and similar registrations would only partially apply (e.g. a route added after some workers already built their URL map), so Flask fails loudly instead of applying changes inconsistently. Added as a hard error in Flask 2.3.","triggerScenarios":"Calling any setup method — `@app.route`, `add_url_rule`, `before_request`, `errorhandler`, `register_blueprint`, `teardown_request`, etc. — after the app has handled at least one request. Typical shapes: registering a route inside a view function or `before_request` callback, lazily importing a module that decorates routes only when a request first touches it, or a test that calls `app.test_client().get(...)` and then adds more routes to the same app instance.","commonSituations":"Lazy/conditional imports of view modules inside request handlers; app factories that return a shared module-level app which tests mutate after exercising it; plugin systems that register endpoints on demand; upgrading from Flask <2.3 where `before_first_request` existed and some of these patterns went unnoticed.","solutions":["Move all route/handler registration to import time or inside your `create_app()` factory, before the app is served.","In tests, create a fresh app per test (pytest fixture calling the factory) instead of mutating one shared instance after requests ran.","If you genuinely need per-request dynamic dispatch, register one catch-all route up front and dispatch inside it rather than adding rules at runtime."],"exampleFix":"# before\n@app.route(\"/\")\ndef index():\n    @app.route(\"/late\")  # raises after first request\n    def late():\n        return \"hi\"\n    return \"ok\"\n\n# after\n@app.route(\"/\")\ndef index():\n    return \"ok\"\n\n@app.route(\"/late\")\ndef late():\n    return \"hi\"","handlingStrategy":"validation","validationCode":"if not app._got_first_request:\n    app.before_request(my_hook)\nelse:\n    raise RuntimeError('Too late to register setup hooks')","typeGuard":"def can_still_setup(app):\n    return not getattr(app, '_got_first_request', False)","tryCatchPattern":"try:\n    app.before_request(hook)\nexcept AssertionError:\n    log.error('Setup method called after first request; move registration to app factory')","preventionTips":["Do all route/hook/extension registration in the app factory before returning the app","Never register decorators lazily inside request handlers or on-demand imports","In tests, build a fresh app per test instead of mutating a shared app that already served requests"],"tags":["flask","python","lifecycle","routing","setup"],"analyzedSha":"6a2f545bfd8ed31e19066a299296917e034aca58","analyzedAt":"2026-07-31T19:13:49.921Z","schemaVersion":2}