{"id":"6d1f2a720132954d","repo":"pallets/flask","slug":"session-backend-did-not-open-a-session","errorCode":null,"errorMessage":"Session backend did not open a session.","messagePattern":"Session backend did not open a session\\.","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"src/flask/testing.py","lineNumber":168,"sourceCode":"        request context and since session handling could depend on\n        request variables this function accepts the same arguments as\n        :meth:`~flask.Flask.test_request_context` which are directly\n        passed through.\n        \"\"\"\n        if self._cookies is None:\n            raise TypeError(\n                \"Cookies are disabled. Create a client with 'use_cookies=True'.\"\n            )\n\n        app = self.application\n        ctx = app.test_request_context(*args, **kwargs)\n        self._add_cookies_to_wsgi(ctx.request.environ)\n\n        with ctx:\n            sess = app.session_interface.open_session(app, ctx.request)\n\n        if sess is None:\n            raise RuntimeError(\"Session backend did not open a session.\")\n\n        yield sess\n        resp = app.response_class()\n\n        if app.session_interface.is_null_session(sess):\n            return\n\n        with ctx:\n            app.session_interface.save_session(app, sess, resp)\n\n        self._update_cookies_from_response(\n            ctx.request.host.partition(\":\")[0],\n            ctx.request.path,\n            resp.headers.getlist(\"Set-Cookie\"),\n        )\n\n    def _copy_environ(self, other: WSGIEnvironment) -> WSGIEnvironment:\n        out = {**self.environ_base, **other}","sourceCodeStart":150,"sourceCodeEnd":186,"githubUrl":"https://github.com/pallets/flask/blob/6a2f545bfd8ed31e19066a299296917e034aca58/src/flask/testing.py#L150-L186","documentation":"Raised as a RuntimeError by `session_transaction()` when `app.session_interface.open_session(app, request)` returns None inside the temporary test request context. Flask's default SecureCookieSessionInterface always returns a session object, so this indicates a custom or third-party session interface that failed to produce one — typically due to missing configuration or backend connectivity.","triggerScenarios":"Using `with client.session_transaction():` while `app.session_interface` is a custom interface whose `open_session` returns None — e.g. it requires `SECRET_KEY` or a live backing store (Redis, database) that isn't available in the test environment. (With the default interface and no SECRET_KEY, older Flask versions returned None here; modern default returns a NullSession instead.)","commonSituations":"Server-side session extensions (Flask-Session and similar) configured against a Redis/memcached instance not running in CI; custom session interfaces that return None on missing config instead of a NullSession; forgetting to set `SECRET_KEY` in the test app config with an interface that gates on it.","solutions":["Set `app.config['SECRET_KEY']` in your test setup before creating the client.","Ensure the session backend (Redis, DB, etc.) used by your session interface is reachable in the test environment, or swap in the default cookie session interface for tests.","Fix a custom `SessionInterface.open_session` to return a `NullSession`/new session rather than None when the store is empty."],"exampleFix":"# before\napp = Flask(__name__)\napp.session_interface = MyRedisSessionInterface()  # redis down in CI\n# after\napp = Flask(__name__)\napp.config[\"SECRET_KEY\"] = \"test\"\nif app.testing:\n    pass  # keep default cookie sessions in tests\nelse:\n    app.session_interface = MyRedisSessionInterface()","handlingStrategy":"validation","validationCode":"app.secret_key = 'test-secret'  # required for the default cookie session backend\nwith app.test_client() as client:\n    with client.session_transaction() as sess:\n        sess['k'] = 'v'","typeGuard":null,"tryCatchPattern":"try:\n    with client.session_transaction() as sess:\n        ...\nexcept RuntimeError as e:\n    if 'did not open a session' in str(e):\n        # secret_key missing or custom session interface returned None\n        raise","preventionTips":["Set app.secret_key (or SECRET_KEY config) in the test app factory before using session_transaction","If you use a custom session interface, ensure open_session never returns None in testing","Verify session config in a conftest fixture so every test gets a working backend"],"tags":["flask","testing","session","session-interface"],"analyzedSha":"6a2f545bfd8ed31e19066a299296917e034aca58","analyzedAt":"2026-07-31T19:13:49.921Z","schemaVersion":2}