tiangolo/fastapi · critical · FastAPIError

Response not awaited. There's a high chance that the…

Error message

Response not awaited. There's a high chance that the application code is raising an exception and a dependency with yield has a block with a bare except, or a block with except Exception, and is not raising the exception again. Read more about it in the docs: https://fastapi.tiangolo.com/tutorial/dependencies/dependencies-with-yield/#dependencies-with-yield-and-except

What it means

FastAPIError (RuntimeError) raised in request_response's inner app (routing.py:149). The handler sets response_awaited = False, awaits the endpoint inside an AsyncExitStack, then sets response_awaited = True only after `await response(scope, receive, send)` runs. If a yielding dependency catches the endpoint's exception with a bare `except:` or `except Exception:` and does not re-raise, the exception is swallowed, the response is never sent, response_awaited stays False, and FastAPI raises this error to signal that the response was silently lost.

Solutions

  1. Re-raise in the except block of the yielding dependency: `except Exception: ...; raise`.
  2. Avoid bare `except:` / `except Exception:` around the yield; only handle specific exceptions you intend to suppress.
  3. Log inside the except but always re-raise so FastAPI can produce the error response.
  4. Reproduce with the app in question and check every dependency-with-yield for a swallowing except block.

Example fix

// before
def get_session():
    session = Session(engine)
    try:
        yield session
    except Exception:
        pass  # swallows the endpoint error -> FastAPIError: Response not awaited
    finally:
        session.close()

// after
def get_session():
    session = Session(engine)
    try:
        yield session
    except Exception:
        logger.exception("request failed")
        raise  # let FastAPI handle the error response
    finally:
        session.close()
Defensive patterns

Strategy: try-catch

Validate before calling

# Static check: flag yielding dependencies that swallow exceptions
import ast, pathlib

class YieldExceptChecker(ast.NodeVisitor):
    def __init__(self, path):
        self.path = path; self.issues = []
    def visit_FunctionDef(self, node):
        has_yield = any(isinstance(n, ast.Yield) for n in ast.walk(node))
        if has_yield:
            for n in ast.walk(node):
                if isinstance(n, ast.ExceptHandler):
                    t = n.type
                    bare = t is None
                    broad = isinstance(t, ast.Name) and t.id == "Exception"
                    has_raise = any(isinstance(c, ast.Raise) for c in ast.walk(n))
                    if (bare or broad) and not has_raise:
                        self.issues.append((self.path, n.lineno))
        self.generic_visit(node)

for p in pathlib.Path('.').rglob('*.py'):
    YieldExceptChecker(str(p)).visit(ast.parse(p.read_text()))

Try / catch

# In the yielding dependency itself
import logging
log = logging.getLogger(__name__)

def get_db():
    db = Session()
    try:
        yield db
    except Exception:
        log.exception("error during request")
        raise  # MUST re-raise so FastAPI can build the error response
    finally:
        db.close()

Prevention

When it happens

Trigger: A dependency defined with `yield` wraps its yield in try/except that catches the exception raised by the endpoint (bare except or except Exception) and does not re-raise it. The dependency's teardown runs, swallows the error, and the response coroutine never executes.

Common situations: Adding try/except around `yield` in a DB-session or resource dependency to 'log and continue'; catching Exception to suppress errors; upgrading an app where a dependency silently absorbed errors that FastAPI now detects.

Related errors


AI-assisted analysis of tiangolo/fastapi@3e8d1526d8 (2026-08-11). Data as JSON: /api/errors/054b6a3a7e4f2c4d. Report an issue: GitHub.

Appendix: source

Thrown at fastapi/routing.py:149

        else functools.partial(run_in_threadpool, func)  # type: ignore[call-arg]
    )  # ty: ignore[invalid-assignment]

    async def app(scope: Scope, receive: Receive, send: Send) -> None:
        request = Request(scope, receive, send)

        async def app(scope: Scope, receive: Receive, send: Send) -> None:
            # Starts customization
            response_awaited = False
            async with AsyncExitStack() as request_stack:
                scope["fastapi_inner_astack"] = request_stack
                async with AsyncExitStack() as function_stack:
                    scope["fastapi_function_astack"] = function_stack
                    response = await f(request)
                await response(scope, receive, send)
                # Continues customization
                response_awaited = True
            if not response_awaited:
                raise FastAPIError(
                    "Response not awaited. There's a high chance that the "
                    "application code is raising an exception and a dependency with yield "
                    "has a block with a bare except, or a block with except Exception, "
                    "and is not raising the exception again. Read more about it in the "
                    "docs: https://fastapi.tiangolo.com/tutorial/dependencies/dependencies-with-yield/#dependencies-with-yield-and-except"
                )

        # Same as in Starlette
        await wrap_app_handling_exceptions(app, request)(scope, receive, send)

    return app


# Copy of starlette.routing.websocket_session modified to include the
# dependencies' AsyncExitStack
def websocket_session(
    func: Callable[[WebSocket], Awaitable[None]],
) -> ASGIApp:

View on GitHub (pinned to 3e8d1526d8)