{"id":"054b6a3a7e4f2c4d","repo":"tiangolo/fastapi","slug":"response-not-awaited-there-s-a-high-chance-that-t","errorCode":null,"errorMessage":"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","messagePattern":"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","errorType":"exception","errorClass":"FastAPIError","httpStatus":null,"severity":"error","filePath":"fastapi/routing.py","lineNumber":149,"sourceCode":"        else functools.partial(run_in_threadpool, func)  # type: ignore[call-arg]\n    )  # ty: ignore[invalid-assignment]\n\n    async def app(scope: Scope, receive: Receive, send: Send) -> None:\n        request = Request(scope, receive, send)\n\n        async def app(scope: Scope, receive: Receive, send: Send) -> None:\n            # Starts customization\n            response_awaited = False\n            async with AsyncExitStack() as request_stack:\n                scope[\"fastapi_inner_astack\"] = request_stack\n                async with AsyncExitStack() as function_stack:\n                    scope[\"fastapi_function_astack\"] = function_stack\n                    response = await f(request)\n                await response(scope, receive, send)\n                # Continues customization\n                response_awaited = True\n            if not response_awaited:\n                raise FastAPIError(\n                    \"Response not awaited. There's a high chance that the \"\n                    \"application code is raising an exception and a dependency with yield \"\n                    \"has a block with a bare except, or a block with except Exception, \"\n                    \"and is not raising the exception again. Read more about it in the \"\n                    \"docs: https://fastapi.tiangolo.com/tutorial/dependencies/dependencies-with-yield/#dependencies-with-yield-and-except\"\n                )\n\n        # Same as in Starlette\n        await wrap_app_handling_exceptions(app, request)(scope, receive, send)\n\n    return app\n\n\n# Copy of starlette.routing.websocket_session modified to include the\n# dependencies' AsyncExitStack\ndef websocket_session(\n    func: Callable[[WebSocket], Awaitable[None]],\n) -> ASGIApp:","sourceCodeStart":131,"sourceCodeEnd":167,"githubUrl":"https://github.com/tiangolo/fastapi/blob/42a41db11f6882807ac3c057b942178d53b97438/fastapi/routing.py#L131-L167","documentation":"Raised by FastAPI's request handler after the dependency AsyncExitStack exits: a `response_awaited` flag is set True only once `await response(scope, receive, send)` completes (routing.py:144-147). If the path operation raised, line 144 raises and the flag stays False; normally that exception propagates out and this branch is never reached. It is reached only when a dependency-with-yield has a `bare except` / `except Exception` that swallows the exception instead of re-raising, so AsyncExitStack.throw unwinds 'cleanly' and control falls through to the `if not response_awaited` guard at routing.py:148-155. In short: your path operation threw, a yielding dependency ate the error, and no response was ever sent.","triggerScenarios":"A `yield`-based dependency (e.g. `def get_db(): try: yield db except Exception: log(...)` without `raise`) combined with a path operation or nested dependency that raises during the request. Also triggered when the dependency's teardown uses `except` to swallow the GeneratorExit/exception injected by the AsyncExitStack on unwind.","commonSituations":"Session/transaction dependencies that log-and-swallow DB errors; porting sync `yield` generators that used broad `except`; cleanup code written as `try/except` instead of `try/finally`; a sub-dependency raising while a parent yield-dep catches everything 'to keep the app alive'.","solutions":["In every `yield` dependency, re-raise inside `except` blocks: `except Exception: ...; raise`.","Prefer `try / finally` for teardown so cleanup cannot accidentally swallow the propagating exception.","Narrow `except` to specific exception types instead of bare `except` or `except Exception`.","Add a CI/lint check that flags `yield` functions containing `except` without a following `raise`.","Reproduce with the failing endpoint and step through the dependency teardown to find the swallowing `except`."],"exampleFix":"# before\ndef get_db():\n    db = SessionLocal()\n    try:\n        yield db\n    except Exception:\n        logging.exception(\"ignored\")  # swallows the request error\n    finally:\n        db.close()\n\n# after\ndef get_db():\n    db = SessionLocal()\n    try:\n        yield db\n    except Exception:\n        logging.exception(\"will re-raise\")\n        raise\n    finally:\n        db.close()","handlingStrategy":"validation","validationCode":"import ast, inspect, textwrap\n\ndef yield_deps_swallow_exceptions(func) -> list[str]:\n    \"\"\"Best-effort static check: flag yield-funcs whose except blocks lack raise.\"\"\"\n    src = textwrap.dedent(inspect.getsource(func))\n    tree = ast.parse(src)\n    problems = []\n    for node in ast.walk(tree):\n        if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)) and any(\n            isinstance(n, ast.Yield) for n in ast.walk(node)\n        ):\n        for tryn in [n for n in ast.walk(node) if isinstance(n, ast.Try)]:\n            for handler in tryn.handlers:\n                has_raise = any(isinstance(n, ast.Raise) for n in ast.walk(handler))\n                bare = handler.type is None\n                broad = isinstance(handler.type, ast.Name) and handler.type.id == \"Exception\"\n                if (bare or broad) and not has_raise:\n                    problems.append(f\"{func.__name__}:{handler.lineno} swallows without raise\")\n    return problems\n\n# usage at startup / in tests\n# assert yield_deps_swallow_exceptions(get_db) == []","typeGuard":null,"tryCatchPattern":"# The response was never sent, so the connection is already broken.\n# Catch only to log and ensure the process stays healthy; you cannot\n# recover the response.\nfrom fastapi import FastAPI\nfrom fastapi.exceptions import FastAPIError\n\napp = FastAPI()\n\n@app.exception_handler(FastAPIError)\nasync def _handle(request, exc):\n    logging.critical(\"FastAPI routing error: %s\", exc)\n    # surface a clean 500; the socket may already be closed\n    from fastapi.responses import JSONResponse\n    return JSONResponse({\"detail\": \"internal error\"}, status_code=500)","preventionTips":["Always follow `except` in a yield dependency with `raise`.","Use `try / finally` for teardown rather than `try / except`.","Never use bare `except` or `except Exception` in a generator that `yield`s a dependency value.","Add a unit test that raises from a path operation and asserts the dependency sees the exception (and that the client still gets a proper error response)."],"tags":["dependencies","yield","exception-handling","async"],"analyzedSha":"42a41db11f6882807ac3c057b942178d53b97438","analyzedAt":"2026-08-04T19:23:32.007Z","schemaVersion":2}