pallets/flask · error · RuntimeError

Cannot nest client invocations

Error message

Cannot nest client invocations

What it means

Raised as a RuntimeError by `FlaskClient.__enter__` when `preserve_context` is already True, i.e. you entered the same test client as a context manager while it is already inside a `with` block. The `with client:` form preserves request contexts after each request so you can inspect `request`/`session`; nesting would corrupt the preserved-context stack, so Flask forbids it.

Source

Thrown at src/flask/testing.py:251

        self._context_stack.close()

        response = super().open(
            request,
            buffered=buffered,
            follow_redirects=follow_redirects,
        )
        response.json_module = self.application.json  # type: ignore[assignment]

        # Re-push contexts that were preserved during the request.
        for cm in self._new_contexts:
            self._context_stack.enter_context(cm)

        self._new_contexts.clear()
        return response

    def __enter__(self) -> FlaskClient:
        if self.preserve_context:
            raise RuntimeError("Cannot nest client invocations")
        self.preserve_context = True
        return self

    def __exit__(
        self,
        exc_type: type | None,
        exc_value: BaseException | None,
        tb: TracebackType | None,
    ) -> None:
        self.preserve_context = False
        self._context_stack.close()


class FlaskCliRunner(CliRunner):
    """A :class:`~click.testing.CliRunner` for testing a Flask app's
    CLI commands. Typically created using
    :meth:`~flask.Flask.test_cli_runner`. See :ref:`testing-cli`.
    """

View on GitHub ↗ (pinned to 6a2f545bfd)

Solutions

  1. Remove the inner `with client:` — use the already-entered client directly.
  2. Enter the client in exactly one place (either the fixture or the test, not both).
  3. If you genuinely need parallel independent request contexts, create a second client with `app.test_client()`.

Example fix

# before
with client:
    with client:  # RuntimeError
        client.get("/")
# after
with client:
    client.get("/")
    assert request.path == "/"
Defensive patterns

Strategy: validation

Validate before calling

# don't call the client inside a route/before-request handler triggered by the same client
# perform sequential requests instead:
r1 = client.get('/a')
r2 = client.get('/b')  # after r1 completes

Try / catch

try:
    resp = client.get('/endpoint')
except RuntimeError as e:
    if 'Cannot nest client invocations' in str(e):
        # a request handler is re-invoking the same test client
        raise

Prevention

When it happens

Trigger: `with client:` inside another `with client:` on the same FlaskClient instance; re-entering a client that was never exited (e.g. an exception path skipped `__exit__`, or a fixture yields an already-entered client and a test enters it again).

Common situations: Pytest fixtures that do `with app.test_client() as client: yield client` combined with tests that also write `with client:`; helper functions that wrap requests in `with self.client:` and get called from within another such block.

Related errors


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