pallets/flask · error · RuntimeError

The session is unavailable because no secret key was set. S

Error message

The session is unavailable because no secret key was set.  Set the secret_key on the application to something unique and secret.

What it means

When Flask's default session interface cannot open a signed cookie session because `app.secret_key` is unset, it substitutes a `NullSession` (src/flask/sessions.py:83-97). Reads return an empty session, but every mutating method (`__setitem__`, `pop`, `clear`, `update`, etc.) is bound to `_fail`, which raises this RuntimeError. It exists to give a clear message instead of silently issuing unsigned, tamperable session cookies.

Source

Thrown at src/flask/sessions.py:90

    def __init__(
        self,
        initial: c.Mapping[str, t.Any] | None = None,
    ) -> None:
        def on_update(self: te.Self) -> None:
            self.modified = True

        super().__init__(initial, on_update)


class NullSession(SecureCookieSession):
    """Class used to generate nicer error messages if sessions are not
    available.  Will still allow read-only access to the empty session
    but fail on setting.
    """

    def _fail(self, *args: t.Any, **kwargs: t.Any) -> t.NoReturn:
        raise RuntimeError(
            "The session is unavailable because no secret "
            "key was set.  Set the secret_key on the "
            "application to something unique and secret."
        )

    __setitem__ = __delitem__ = clear = pop = popitem = update = setdefault = _fail
    del _fail


class SessionInterface:
    """The basic interface you have to implement in order to replace the
    default session interface which uses werkzeug's securecookie
    implementation.  The only methods you have to implement are
    :meth:`open_session` and :meth:`save_session`, the others have
    useful defaults which you don't need to change.

    The session object returned by the :meth:`open_session` method has to
    provide a dictionary like interface plus the properties and methods

View on GitHub ↗ (pinned to 6a2f545bfd)

Solutions

  1. Set a secret key before handling requests: `app.secret_key = '...'` or `app.config['SECRET_KEY'] = '...'` (load from an env var; generate with `python -c "import secrets; print(secrets.token_hex(32))"`).
  2. Fail fast on missing configuration: raise at startup if `SECRET_KEY` is unset rather than discovering it on first session write.
  3. Verify the env var actually reaches the process (Docker/compose env, systemd unit, CI secrets) — reference it by name, don't print the value.
  4. If sessions are intentionally unused, remove the `session`/`flash`/login calls instead.

Example fix

# before
app = Flask(__name__)

@app.route('/login', methods=['POST'])
def login():
    session['user'] = request.form['user']  # RuntimeError

# after
app = Flask(__name__)
app.secret_key = os.environ['SECRET_KEY']  # fail fast if unset
Defensive patterns

Strategy: validation

Validate before calling

import os

app.secret_key = os.environ["FLASK_SECRET_KEY"]  # fail fast at startup
assert app.secret_key, "FLASK_SECRET_KEY must be set before using sessions"

Type guard

def sessions_enabled(app) -> bool:
    return bool(app.secret_key or app.config.get("SECRET_KEY"))

Try / catch

try:
    session["user_id"] = user.id
except RuntimeError as exc:
    if "secret key" in str(exc):
        raise RuntimeError("SECRET_KEY not configured; set FLASK_SECRET_KEY") from exc
    raise

Prevention

When it happens

Trigger: Any write to `flask.session` (e.g. `session['user_id'] = 1`, `session.pop('cart')`, `session.clear()`) while `app.secret_key`/`app.config['SECRET_KEY']` is None. Also triggered indirectly by `flask_login.login_user()`, `flash()`, or CSRF extensions that store tokens in the session.

Common situations: New projects that never set SECRET_KEY; setting it via an env var (`SECRET_KEY=os.environ.get('SECRET_KEY')`) that is missing in production/Docker; setting config after blueprints already captured it; app-factory setups where config loading is skipped in a worker; `flash()` calls failing in tutorials.

Related errors


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