pallets/flask · error · TypeError
{e}\nThe view function did not return a valid response. The
Error message
{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 was a {type(rv).__name__}. What it means
Raised when Flask attempts to coerce a callable/WSGI response via Response.force_type and that raises a TypeError. The original TypeError message is prepended with guidance listing accepted return types, so the developer sees both the underlying cause and the contract.
Source
Thrown at src/flask/app.py:1339
# 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 3596b1ab61)
Solutions
- Return a Response object directly instead of a raw WSGI callable.
- Ensure the callable conforms to PEP 3333 (yields bytes, status/headers set).
- Pin compatible Werkzeug/Flask versions if a BaseResponse mismatch is the cause.
Example fix
// before
@app.route('/x')
def x():
return some_broken_wsgi_callable # force_type raises TypeError
// after
from flask import Response
@app.route('/x')
def x():
return Response('ok', status=200) Defensive patterns
Strategy: validation
Validate before calling
def to_response(rv, response_class):
if isinstance(rv, (str, bytes, bytearray)):
return response_class(rv)
return response_class.force_type(rv, request.environ) Type guard
from collections.abc import Callable
def is_acceptable_callable(rv) -> bool:
return callable(rv) or hasattr(rv, '__call__') Try / catch
try:
rv = response_class.force_type(value, environ)
except TypeError:
rv = Response('Internal type error', status=500) Prevention
- Return Response objects directly instead of raw WSGI callables.
- Validate WSGI callables conform to PEP 3333 before use.
- Keep Werkzeug/Flask versions aligned.
When it happens
Trigger: A view returns a callable or BaseResponse subclass that force_type cannot convert (e.g. a generator-based WSGI callable that itself errors, or a BaseResponse from an incompatible library version).
Common situations: Returning a custom WSGI callable that yields non-byte values; mixing Werkzeug versions where BaseResponse API differs; returning an object whose __call__ raises TypeError.
Related errors
- The view function did not return a valid response tuple. The
- The view function for {request.endpoint!r} did not return a
- The view function did not return a valid response. The retur
- Allowed methods must be a list of strings, for example: @app
- Use the 'route' decorator to use the 'methods' argument.
AI-assisted analysis of pallets/flask@3596b1ab61 (2026-08-11).
Data as JSON: /api/errors/d676d6fb481255d7.
Report an issue: GitHub.