pallets/flask · error · RuntimeError
'stream_with_context' can only be used when a request…
Error message
'stream_with_context' can only be used when a request context is active, such as in a view function.
What it means
stream_with_context wraps a generator so it keeps the request context alive after the response starts streaming. Inside the inner generator() it reads _cv_app.get(None); if None (no request context active at the moment the generator first runs), it raises RuntimeError. The context must be active when the generator begins iterating, not just when stream_with_context is called.
Solutions
- Apply stream_with_context inside the view function so the generator captures the active request context: return stream_with_context(gen()).
- Ensure the generator is consumed synchronously within the response lifecycle; do not hand it to a background thread without its own context handling.
- If streaming from a function, use the decorator form @stream_with_context so the context is captured at call time.
Example fix
# before
@app.route('/stream')
def stream():
def gen():
yield request.headers['X-Id'] # may lose context after response
return Response(gen())
# after
@app.route('/stream')
def stream():
def gen():
yield request.headers['X-Id']
return Response(stream_with_context(gen())) Defensive patterns
Strategy: type-guard
Validate before calling
from flask import has_request_context
def can_stream_with_context() -> bool:
return has_request_context() Type guard
from flask import has_request_context
def in_request_context() -> bool:
return has_request_context() Try / catch
from flask import has_request_context
if not has_request_context():
raise RuntimeError('stream_with_context must run within a request context')
return Response(stream_with_context(gen())) Prevention
- Call stream_with_context inside the view, not in a background task.
- Consume the streamed generator within the response lifecycle.
When it happens
Trigger: Calling stream_with_context on a generator that is consumed outside a request context (e.g. the generator is materialized in a background task, or the wrapping runs after the request ended). Also if the decorated function is invoked without an active request context. The walrus check (ctx := _cv_app.get(None)) is None triggers the raise.
Common situations: Starting a background thread that iterates the streamed generator after the original request returned. Forgetting to call stream_with_context inside the view. Returning a raw generator without the wrapper in streaming responses.
Related errors
- 'after_this_request' can only be used when a request…
- 'copy_current_request_context' can only be used when a…
- 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/4c4104fd5a665ce2.
Report an issue: GitHub.
Appendix: source
Thrown at src/flask/helpers.py:128
yield "!"
return Response(stream_with_context(generate()))
.. versionadded:: 0.9
"""
try:
gen = iter(generator_or_function) # type: ignore[arg-type]
except TypeError:
def decorator(*args: t.Any, **kwargs: t.Any) -> t.Any:
gen = generator_or_function(*args, **kwargs) # type: ignore[operator]
return stream_with_context(gen)
return update_wrapper(decorator, generator_or_function) # type: ignore[arg-type]
def generator() -> t.Iterator[t.AnyStr]:
if (ctx := _cv_app.get(None)) is None:
raise RuntimeError(
"'stream_with_context' can only be used when a request"
" context is active, such as in a view function."
)
with ctx:
yield None # type: ignore[misc]
try:
yield from gen
finally:
# Clean up in case the user wrapped a WSGI iterator.
if hasattr(gen, "close"):
gen.close()
# Execute the generator to the sentinel value. This captures the current
# context and pushes it to preserve it. Further iteration will yield from
# the original iterator.
wrapped_g = generator()View on GitHub (pinned to 3596b1ab61)