{"id":"7bc604da45dad3e1","repo":"pallets/flask","slug":"copy-current-request-context-can-only-be-used-wh","errorCode":null,"errorMessage":"'copy_current_request_context' can only be used when a request context is active, such as in a view function.","messagePattern":"'copy_current_request_context' can only be used when a request context is active, such as in a view function\\.","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"src/flask/ctx.py","lineNumber":196,"sourceCode":"        from flask import copy_current_request_context\n\n        @app.route('/')\n        def index():\n            @copy_current_request_context\n            def do_some_work():\n                # do some work here, it can access flask.request or\n                # flask.session like you would otherwise in the view function.\n                ...\n            gevent.spawn(do_some_work)\n            return 'Regular response'\n\n    .. versionadded:: 0.10\n    \"\"\"\n    # Store the context that was active when the decorator was applied.\n    original = _cv_app.get(None)\n\n    if original is None:\n        raise RuntimeError(\n            \"'copy_current_request_context' can only be used when a\"\n            \" request context is active, such as in a view function.\"\n        )\n\n    def wrapper(*args: t.Any, **kwargs: t.Any) -> t.Any:\n        # Copy the context before pushing, so each worker acts independently.\n        with original.copy() as ctx:\n            return ctx.app.ensure_sync(f)(*args, **kwargs)\n\n    return update_wrapper(wrapper, f)  # type: ignore[return-value]\n\n\ndef has_request_context() -> bool:\n    \"\"\"Test if an app context is active and if it has request information.\n\n    .. code-block:: python\n\n        from flask import has_request_context, request","sourceCodeStart":178,"sourceCodeEnd":214,"githubUrl":"https://github.com/pallets/flask/blob/6a2f545bfd8ed31e19066a299296917e034aca58/src/flask/ctx.py#L178-L214","documentation":"`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.","triggerScenarios":"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.","commonSituations":"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()`.","solutions":["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.","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.","In tests, apply the decorator inside `with app.test_request_context(): ...`."],"exampleFix":"# before\n@copy_current_request_context  # module level -> RuntimeError\ndef do_work():\n    print(request.path)\n\n# after\n@app.route('/')\ndef index():\n    @copy_current_request_context\n    def do_work():\n        print(request.path)\n    Thread(target=do_work).start()\n    return 'ok'","handlingStrategy":"type-guard","validationCode":"from flask import has_request_context, copy_current_request_context\n\nif has_request_context():\n    task = copy_current_request_context(do_work)\nelse:\n    task = do_work  # run without request state, passing data explicitly","typeGuard":"from flask import has_request_context\n\ndef can_copy_request_context() -> bool:\n    return has_request_context()","tryCatchPattern":"try:\n    wrapped = copy_current_request_context(worker)\nexcept RuntimeError:\n    # No active request: pass the needed values as plain arguments instead\n    wrapped = functools.partial(worker_without_ctx, data=payload)","preventionTips":["Call `copy_current_request_context` inside the view, before spawning the thread/greenlet — not inside the spawned function.","Prefer extracting the specific values you need from `request` and passing them as arguments; copying the whole context is a last resort.","Guard with `has_request_context()` when the same code path is reachable from CLI or background jobs."],"tags":["flask","python","request-context","concurrency","decorators"],"analyzedSha":"6a2f545bfd8ed31e19066a299296917e034aca58","analyzedAt":"2026-07-31T19:13:49.921Z","schemaVersion":2}