pallets/flask · error · RuntimeError

Session backend did not open a session.

Error message

Session backend did not open a session.

What it means

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.

Source

Thrown at src/flask/testing.py:168

        request context and since session handling could depend on
        request variables this function accepts the same arguments as
        :meth:`~flask.Flask.test_request_context` which are directly
        passed through.
        """
        if self._cookies is None:
            raise TypeError(
                "Cookies are disabled. Create a client with 'use_cookies=True'."
            )

        app = self.application
        ctx = app.test_request_context(*args, **kwargs)
        self._add_cookies_to_wsgi(ctx.request.environ)

        with ctx:
            sess = app.session_interface.open_session(app, ctx.request)

        if sess is None:
            raise RuntimeError("Session backend did not open a session.")

        yield sess
        resp = app.response_class()

        if app.session_interface.is_null_session(sess):
            return

        with ctx:
            app.session_interface.save_session(app, sess, resp)

        self._update_cookies_from_response(
            ctx.request.host.partition(":")[0],
            ctx.request.path,
            resp.headers.getlist("Set-Cookie"),
        )

    def _copy_environ(self, other: WSGIEnvironment) -> WSGIEnvironment:
        out = {**self.environ_base, **other}

View on GitHub ↗ (pinned to 6a2f545bfd)

Solutions

  1. Set `app.config['SECRET_KEY']` in your test setup before creating the client.
  2. 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.
  3. Fix a custom `SessionInterface.open_session` to return a `NullSession`/new session rather than None when the store is empty.

Example fix

# before
app = Flask(__name__)
app.session_interface = MyRedisSessionInterface()  # redis down in CI
# after
app = Flask(__name__)
app.config["SECRET_KEY"] = "test"
if app.testing:
    pass  # keep default cookie sessions in tests
else:
    app.session_interface = MyRedisSessionInterface()
Defensive patterns

Strategy: validation

Validate before calling

app.secret_key = 'test-secret'  # required for the default cookie session backend
with app.test_client() as client:
    with client.session_transaction() as sess:
        sess['k'] = 'v'

Try / catch

try:
    with client.session_transaction() as sess:
        ...
except RuntimeError as e:
    if 'did not open a session' in str(e):
        # secret_key missing or custom session interface returned None
        raise

Prevention

When it happens

Trigger: 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.)

Common situations: 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.

Related errors


AI-assisted analysis of pallets/flask@6a2f545bfd (2026-07-31). Data as JSON: /data/errors/6d1f2a720132954d.json. Report an issue: GitHub ↗.