pallets/flask · error · TypeError

{e} The view function did not return a valid response. The r

Error message

{e}
The view function did not return a valid response. The return type must be a string, dict, list, tuple with headers or status, Response instance, or WSGI callable, but it was a {type(rv).__name__}.

What it means

Raised in `Flask.make_response()` (src/flask/app.py:1336) when the return value looked like a Response instance (another framework's `BaseResponse` subclass) or a callable/WSGI app, but `response_class.force_type()` failed to coerce it, raising a TypeError. Flask re-raises with the original coercion error (`{e}`) prepended plus the list of valid return types, because a callable that isn't actually a valid WSGI application cannot be turned into a Flask Response.

Source

Thrown at src/flask/app.py:1336

                # special logic
                rv = self.response_class(
                    rv,  # pyright: ignore
                    status=status,
                    headers=headers,  # type: ignore[arg-type]
                )
                status = headers = None
            elif isinstance(rv, (dict, list)):
                rv = self.json.response(rv)
            elif isinstance(rv, BaseResponse) or callable(rv):
                # evaluate a WSGI callable, or coerce a different response
                # class to the correct type
                try:
                    rv = self.response_class.force_type(
                        rv,  # type: ignore[arg-type]
                        request.environ,
                    )
                except TypeError as e:
                    raise TypeError(
                        f"{e}\nThe view function did not return a valid"
                        " response. The return type must be a string,"
                        " dict, list, tuple with headers or status,"
                        " Response instance, or WSGI callable, but it"
                        f" was a {type(rv).__name__}."
                    ).with_traceback(sys.exc_info()[2]) from None
            else:
                raise TypeError(
                    "The view function did not return a valid"
                    " response. The return type must be a string,"
                    " dict, list, tuple with headers or status,"
                    " Response instance, or WSGI callable, but it was a"
                    f" {type(rv).__name__}."
                )

        rv = t.cast(Response, rv)
        # prefer the status if it was provided
        if status is not None:

View on GitHub ↗ (pinned to 6a2f545bfd)

Solutions

  1. Read the first line of the message (the original coercion error) — it identifies why werkzeug's force_type failed.
  2. If you meant to call a function, add the parentheses: `return build_response()` not `return build_response`.
  3. Convert the object explicitly before returning: `return make_response(str(obj))`, `return jsonify(obj_dict)`, or construct a `flask.Response` yourself.
  4. Only return a raw callable if it is a genuine WSGI application accepting `(environ, start_response)`.

Example fix

# before
def build_report():
    return render_template("report.html")

@app.route("/report")
def report():
    return build_report  # returned the function object

# after
@app.route("/report")
def report():
    return build_report()
Defensive patterns

Strategy: type-guard

Type guard

from flask import Response
def is_returnable(rv) -> bool:
    return isinstance(rv, (str, bytes, dict, list, tuple, Response)) or callable(rv)

Try / catch

try:
    resp = app.make_response(rv)
except TypeError:
    # rv was an unsupported type (e.g. int, ORM model, generator object)
    raise

Prevention

When it happens

Trigger: Returning a callable that doesn't implement the WSGI signature `(environ, start_response)` — e.g. a function, lambda, class, or partially-applied object returned by mistake; returning a foreign response object whose iteration/coercion fails inside `werkzeug.Response.force_type`.

Common situations: Returning a function reference instead of calling it (`return my_handler` instead of `return my_handler()`); returning a class like `return MyModel`; returning an ORM object or generator-producing callable; mixing response objects from an incompatible library version where force_type's coercion breaks.

Related errors


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