pallets/flask · error · RuntimeError
'after_this_request' can only be used when a request…
Error message
'after_this_request' can only be used when a request context is active, such as in a view function.
What it means
after_this_request(f) reads the current app context from _cv_app. If ctx is None (no app context) or ctx.has_request is False (an app context is active but no request is bound to it), it raises RuntimeError. The function only makes sense within an active request because it queues f onto the current request's after-request chain.
Solutions
- Move the after_this_request call inside a view function where a request context is active.
- For background work, wrap the worker in copy_current_request_context and call after_this_request from within that copied context.
- In tests, push a request context with app.test_request_context() before invoking code that uses after_this_request.
Example fix
# before
@app.route('/')
def index():
return 'hi'
after_this_request(add_header) # at module level -> RuntimeError
# after
@app.route('/')
def index():
after_this_request(add_header)
return 'hi' Defensive patterns
Strategy: type-guard
Validate before calling
from flask import has_request_context
def safe_after_this_request(f):
if not has_request_context():
raise RuntimeError('after_this_request requires a request context')
from flask import after_this_request
return after_this_request(f) Type guard
from flask import has_request_context
def in_request_context() -> bool:
return has_request_context() Try / catch
try:
after_this_request(add_header)
except RuntimeError:
# queue the work another way, e.g. store on g or defer
pass Prevention
- Only call after_this_request inside view functions.
- Use flask.has_request_context() to guard before calling.
When it happens
Trigger: Calling after_this_request(...) outside a view function—e.g. at import time, in a background thread without a request context, in a shell command, or in an app-context-only block (with app.app_context() but no test_request_context/request). The check is ctx is None or not ctx.has_request.
Common situations: Registering a cleanup hook from a module-level function. Using after_this_request inside a teardown or before_first_request handler. Background workers spawned without copying the request context.
Related errors
- 'copy_current_request_context' can only be used when a…
- 'stream_with_context' can only be used when a request…
- There is no request in this context.
- Cannot pop this context
- Cannot pop this context
AI-assisted analysis of pallets/flask@3596b1ab61 (2026-08-11).
Data as JSON: /api/errors/bc8a3c7c21374fcf.
Report an issue: GitHub.
Appendix: source
Thrown at src/flask/ctx.py:142
request context, rather than during setup.
.. code-block:: python
@app.route("/")
def index():
@after_this_request
def add_header(response):
response.headers["X-Foo"] = "Parachute"
return response
return "Hello, World!"
.. versionadded:: 0.9
"""
ctx = _cv_app.get(None)
if ctx is None or not ctx.has_request:
raise RuntimeError(
"'after_this_request' can only be used when a request"
" context is active, such as in a view function."
)
ctx._after_request_functions.append(f)
return f
F = t.TypeVar("F", bound=t.Callable[..., t.Any])
def copy_current_request_context(f: F) -> F:
"""Decorate a function to run inside the current request context. This can
be used when starting a background task, otherwise it will not see the app
and request objects that were active in the parent.
.. warning::
View on GitHub (pinned to 3596b1ab61)