pallets/flask · error · RuntimeError

Cannot pop this context ({self!r}), there is no active conte

Error message

Cannot pop this context ({self!r}), there is no active context.

What it means

After confirming the context was pushed, `pop()` reads the currently active context from the `flask.app_ctx` ContextVar and raises this RuntimeError if none is set (src/flask/ctx.py:468-473). This means the context believes it is pushed (`_cv_token` set) but the ContextVar in the current execution context is empty — the push and pop are happening in different threads, greenlets, or asyncio tasks, since ContextVars are per-execution-context.

Source

Thrown at src/flask/ctx.py:471

        This context must currently be the active context, otherwise a
        :exc:`RuntimeError` is raised. In some situations, such as streaming or
        testing, the context may have been pushed multiple times. It will only
        trigger cleanup once it has been popped as many times as it was pushed.
        Until then, it will remain the active context.

        :param exc: An unhandled exception that was raised while the context was
            active. Passed to teardown functions.

        .. versionchanged:: 0.9
            Added the ``exc`` argument.
        """
        if self._cv_token is None:
            raise RuntimeError(f"Cannot pop this context ({self!r}), it is not pushed.")

        ctx = _cv_app.get(None)

        if ctx is None or self._cv_token is None:
            raise RuntimeError(
                f"Cannot pop this context ({self!r}), there is no active context."
            )

        if ctx is not self:
            raise RuntimeError(
                f"Cannot pop this context ({self!r}), it is not the active"
                f" context ({ctx!r})."
            )

        self._push_count -= 1

        if self._push_count > 0:
            return

        collect_errors = _CollectErrors()

        if self._request is not None:
            with collect_errors:

View on GitHub ↗ (pinned to 6a2f545bfd)

Solutions

  1. Push and pop the context in the same thread/task — ideally by replacing manual management with a `with` block so entry and exit share one execution context.
  2. For background work, create a fresh context in the worker (`with app.app_context():` or `ctx.copy()` via `copy_current_request_context`) instead of popping the parent's context.
  3. In async code, ensure setup and teardown run in the same task, or use an async context manager wrapping both.

Example fix

# before
ctx = app.app_context()
ctx.push()  # in main thread
Thread(target=ctx.pop).start()  # pops in another thread -> RuntimeError

# after
def worker(app):
    with app.app_context():
        do_work()
Thread(target=worker, args=(app,)).start()
Defensive patterns

Strategy: validation

Validate before calling

from flask import has_app_context

if has_app_context():
    ctx.pop()
# else: nothing is pushed in this execution flow — skip the pop

Type guard

from flask import has_app_context, has_request_context

def any_context_active() -> bool:
    return has_app_context() or has_request_context()

Try / catch

try:
    ctx.pop()
except RuntimeError:
    # Context was already popped or belongs to another flow;
    # indicates unbalanced push/pop — fix the lifecycle, don't swallow silently
    logger.exception("unbalanced Flask context pop")
    raise

Prevention

When it happens

Trigger: Pushing a context in one thread/task and calling `pop()` from another (e.g. push in a test's setup thread, pop in a worker thread or an asyncio task); popping after an executor/greenlet switch where the ContextVar didn't propagate; teardown code running in a different event-loop task than the push.

Common situations: Async test frameworks or fixtures where setup and teardown run in different tasks; background workers that receive a context object from the spawning request and try to pop it; custom middleware doing push/pop across gevent hub switches; long-lived context objects stored globally and popped from arbitrary threads.

Related errors


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