{"record":{"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/3596b1ab61cea85edb8970e83ff61daa073facf8/src/flask/sansio/app.py#L394-L430","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\n@app.route('/first')\ndef first(): return 'hi'\n\n@app.after_request  # called after first request in a test\ndef add_header(resp): return resp\n\n// after - register all setup at import time, before any request\n@app.route('/first')\ndef first(): return 'hi'\n\n@app.after_request\ndef add_header(resp): return resp\n# ensure app.run()/client calls happen only after all setup is imported","handlingStrategy":"validation","validationCode":"def assert_app_settable(app):\n    if getattr(app, '_got_first_request', False):\n        raise RuntimeError('app already served first request; register routes earlier')\n","typeGuard":"def is_app_setup_open(app) -> bool:\n    return not getattr(app, '_got_first_request', False)\n","tryCatchPattern":"try:\n    app.add_url_rule('/x', view_func=handler)\nexcept AssertionError as e:\n    if 'setup method' in str(e):\n        # move registration to startup; do not swallow silently\n        raise","preventionTips":["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."],"tags":["flask","lifecycle","setup","assertion","configuration"],"backgroundTag":null,"analyzedSha":"3596b1ab61cea85edb8970e83ff61daa073facf8","analyzedAt":"2026-08-11T20:11:52.622Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}