pallets/flask · error · RuntimeError

'copy_current_request_context' can only be used when a reque

Error message

'copy_current_request_context' can only be used when a request context is active, such as in a view function.

What it means

`copy_current_request_context` captures the currently active context via `_cv_app.get(None)` at decoration time so the wrapped function can later run inside a copy of it, e.g. in a spawned greenlet or thread (src/flask/ctx.py:154-206). If no context is active when the decorator is applied, there is nothing to copy, so it raises this RuntimeError. The capture happens when the decorator runs, not when the wrapped function is called.

Source

Thrown at src/flask/ctx.py:196

        from flask import copy_current_request_context

        @app.route('/')
        def index():
            @copy_current_request_context
            def do_some_work():
                # do some work here, it can access flask.request or
                # flask.session like you would otherwise in the view function.
                ...
            gevent.spawn(do_some_work)
            return 'Regular response'

    .. versionadded:: 0.10
    """
    # Store the context that was active when the decorator was applied.
    original = _cv_app.get(None)

    if original is None:
        raise RuntimeError(
            "'copy_current_request_context' can only be used when a"
            " request context is active, such as in a view function."
        )

    def wrapper(*args: t.Any, **kwargs: t.Any) -> t.Any:
        # Copy the context before pushing, so each worker acts independently.
        with original.copy() as ctx:
            return ctx.app.ensure_sync(f)(*args, **kwargs)

    return update_wrapper(wrapper, f)  # type: ignore[return-value]


def has_request_context() -> bool:
    """Test if an app context is active and if it has request information.

    .. code-block:: python

        from flask import has_request_context, request

View on GitHub ↗ (pinned to 6a2f545bfd)

Solutions

  1. Define and decorate the function inside the view function, so the decorator runs while the request context is active, then spawn the thread/greenlet with the wrapped function.
  2. Prefer passing the needed request data (form fields, headers, user id) into the task explicitly — Flask's own docs note this is safer and simpler.
  3. In tests, apply the decorator inside `with app.test_request_context(): ...`.

Example fix

# before
@copy_current_request_context  # module level -> RuntimeError
def do_work():
    print(request.path)

# after
@app.route('/')
def index():
    @copy_current_request_context
    def do_work():
        print(request.path)
    Thread(target=do_work).start()
    return 'ok'
Defensive patterns

Strategy: type-guard

Validate before calling

from flask import has_request_context, copy_current_request_context

if has_request_context():
    task = copy_current_request_context(do_work)
else:
    task = do_work  # run without request state, passing data explicitly

Type guard

from flask import has_request_context

def can_copy_request_context() -> bool:
    return has_request_context()

Try / catch

try:
    wrapped = copy_current_request_context(worker)
except RuntimeError:
    # No active request: pass the needed values as plain arguments instead
    wrapped = functools.partial(worker_without_ctx, data=payload)

Prevention

When it happens

Trigger: Applying `@copy_current_request_context` outside an active request context — most commonly at module level or on a function defined during app setup, rather than defining the decorated function inside the view that spawns the background task. Also calling it in a worker process where no request was ever dispatched.

Common situations: Decorating a task function at module top-level intending to reuse it across views (the decorator must be applied per-request, inside the view); gevent/threading background-task patterns copied incorrectly from docs; testing the decorated helper without `app.test_request_context()`.

Related errors


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