pallets/flask · error · TypeError
The view function for {request.endpoint!r} did not return a
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 in `Flask.make_response()` (src/flask/app.py:1307) when the view's return value (after tuple unpacking) is None. A WSGI response needs a body, and the most common cause is a view that fell off the end without a `return` statement — Python implicitly returns None — so Flask names the offending endpoint to make the fix obvious.
Source
Thrown at src/flask/app.py:1307
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 6a2f545bfd)
Solutions
- Add a `return` for every code path in the view named in the error message — search it for branches that end without returning.
- Check custom decorators wrapping the view: the wrapper must `return func(*args, **kwargs)`.
- Make sure side-effect calls like `render_template()` or `redirect()` are returned, not just evaluated.
- If a route legitimately has no body, `return ('', 204)` instead of nothing.
Example fix
# before
@app.route("/submit", methods=["GET", "POST"])
def submit():
if request.method == "POST":
return redirect(url_for("done"))
render_template("form.html") # not returned!
# after
@app.route("/submit", methods=["GET", "POST"])
def submit():
if request.method == "POST":
return redirect(url_for("done"))
return render_template("form.html") Defensive patterns
Strategy: validation
Validate before calling
# lint/test guard: every code path must return
# ruff/pylint flag inconsistent-return-statements (R1710)
def view():
if cond:
return render_template('a.html')
return render_template('b.html') # no implicit None fall-through Prevention
- Ensure every branch of a view function returns a value; enable pylint R1710 / mypy strict returns
- Return ('', 204) explicitly for intentionally empty responses instead of returning None
- Cover every conditional branch of each view with a test-client test
When it happens
Trigger: A view function with a missing `return` (e.g. only a code path for POST returns, GET falls through); `return None` explicitly; `return None, 200` or `(None, 200, headers)` — the None body is caught after tuple unpacking; a decorator or `before_request`-style wrapper that swallows the view's return value.
Common situations: Conditional branches where only one branch returns (`if form.validate(): return redirect(...)` with no else); views that call `render_template(...)` without returning it; custom decorators that forget `return f(*args, **kwargs)`; error handlers that log but return nothing; async views where a wrapper dropped the awaited result.
Related errors
- The view function did not return a valid response tuple. The
- {e} The view function did not return a valid response. The r
- The view function did not return a valid response. The retur
- Working outside of application context. Attempted to use fu
- Working outside of request context. Attempted to use functi
AI-assisted analysis of pallets/flask@6a2f545bfd (2026-07-31).
Data as JSON: /data/errors/86949444004012ae.json.
Report an issue: GitHub ↗.