pallets/flask · error · TypeError
The view function for
Error message
The view function for {request.endpoint!r} did not return a valid response. The function either returned None or ended without a return statement. What it means
Raised when a view function's effective body (rv) is None after tuple unpacking. A Flask view must produce a response body; None means the function returned nothing or returned None explicitly, so Flask cannot build a response.
Solutions
- Add an explicit return to every branch, e.g. return '' or return jsonify(...).
- Return a proper Response or status tuple like ('', 204).
- Run a linter/type checker (mypy, pyright) to flag functions missing returns.
Example fix
// before
@app.route('/x')
def x():
log_event() # no return -> raises
// after
@app.route('/x')
def x():
log_event()
return '', 204 Defensive patterns
Strategy: validation
Validate before calling
def require_body(rv):
if rv is None:
raise TypeError('View must return a non-None body')
return rv Type guard
def has_body(rv) -> bool:
return rv is not None Try / catch
try:
return view()
except TypeError as e:
if 'did not return a valid response' in str(e):
return '', 204
raise Prevention
- Ensure every branch returns a value.
- Use mypy/pyright to flag missing-return paths.
- Default to ('', 204) when a view intentionally has no body.
When it happens
Trigger: A view with no return statement, a view that returns None, or a view that returns a tuple whose first element is None.
Common situations: Forgot a return statement after a refactor; early return with no value (return) in a conditional branch; view that logs and implicitly falls through.
Related errors
- \nThe view function did not return a valid response. The…
- The view function did not return a valid response tuple…
- The view function did not return a valid response. The…
- Allowed methods must be a list of strings, for example…
- is an instance, not a class. Handlers can only be…
AI-assisted analysis of pallets/flask@3596b1ab61 (2026-08-11).
Data as JSON: /api/errors/86949444004012ae.
Report an issue: GitHub.
Appendix: source
Thrown at src/flask/app.py:1310
if len_rv == 3:
rv, status, headers = rv # type: ignore[misc]
# decide if a 2-tuple has status or headers
elif len_rv == 2:
if isinstance(rv[1], (Headers, dict, tuple, list)):
rv, headers = rv # pyright: ignore
else:
rv, status = rv # type: ignore[assignment,misc]
# other sized tuples are not allowed
else:
raise TypeError(
"The view function did not return a valid response tuple."
" The tuple must have the form (body, status, headers),"
" (body, status), or (body, headers)."
)
# the body must not be None
if rv is None:
raise TypeError(
f"The view function for {request.endpoint!r} did not"
" return a valid response. The function either returned"
" None or ended without a return statement."
)
# make sure the body is an instance of the response class
if not isinstance(rv, self.response_class):
if isinstance(rv, (str, bytes, bytearray)) or isinstance(rv, cabc.Iterator):
# let the response class set the status and headers instead of
# waiting to do it manually, so that the class can handle any
# 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)):View on GitHub (pinned to 3596b1ab61)