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

  1. Apply stream_with_context inside the view function so the generator captures the active request context: return stream_with_context(gen()).
  2. Ensure the generator is consumed synchronously within the response lifecycle; do not hand it to a background thread without its own context handling.
  3. 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

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


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)