If you use a try block in a dependency with yield, you'll receive any exception that was thrown when using the dependency.
For example, if some code at some point in the middle, in another dependency or in a path operation, made a database transaction "rollback" or create any other error, you will receive the exception in your dependency.
So, you can look for that specific exception inside the dependency with except SomeException.
In the same way, you can use finally to make sure the exit steps are executed, no matter if there was an exception or not.
The same way, you could have some dependencies with yield and some other dependencies with return, and have some of those depend on some of the others.
And you could have a single dependency that requires several other dependencies with yield, etc.
You can have any combinations of dependencies that you want.
FastAPI will make sure everything is run in the correct order.
You saw that you can use dependencies with yield and have try blocks that catch exceptions.
The same way, you could raise an HTTPException or similar in the exit code, after the yield.
Tip
This is a somewhat advanced technique, and in most of the cases you won't really need it, as you can raise exceptions (including HTTPException) from inside of the rest of your application code, for example, in the path operation function.
But it's there for you if you need it. 🤓
fromtypingimportAnnotatedfromfastapiimportDepends,FastAPI,HTTPExceptionapp=FastAPI()data={"plumbus":{"description":"Freshly pickled plumbus","owner":"Morty"},"portal-gun":{"description":"Gun to create portals","owner":"Rick"},}classOwnerError(Exception):passdefget_username():try:yield"Rick"exceptOwnerErrorase:raiseHTTPException(status_code=400,detail=f"Owner error: {e}")@app.get("/items/{item_id}")defget_item(item_id:str,username:Annotated[str,Depends(get_username)]):ifitem_idnotindata:raiseHTTPException(status_code=404,detail="Item not found")item=data[item_id]ifitem["owner"]!=username:raiseOwnerError(username)returnitem
fromfastapiimportDepends,FastAPI,HTTPExceptionfromtyping_extensionsimportAnnotatedapp=FastAPI()data={"plumbus":{"description":"Freshly pickled plumbus","owner":"Morty"},"portal-gun":{"description":"Gun to create portals","owner":"Rick"},}classOwnerError(Exception):passdefget_username():try:yield"Rick"exceptOwnerErrorase:raiseHTTPException(status_code=400,detail=f"Owner error: {e}")@app.get("/items/{item_id}")defget_item(item_id:str,username:Annotated[str,Depends(get_username)]):ifitem_idnotindata:raiseHTTPException(status_code=404,detail="Item not found")item=data[item_id]ifitem["owner"]!=username:raiseOwnerError(username)returnitem
Tip
Prefer to use the Annotated version if possible.
fromfastapiimportDepends,FastAPI,HTTPExceptionapp=FastAPI()data={"plumbus":{"description":"Freshly pickled plumbus","owner":"Morty"},"portal-gun":{"description":"Gun to create portals","owner":"Rick"},}classOwnerError(Exception):passdefget_username():try:yield"Rick"exceptOwnerErrorase:raiseHTTPException(status_code=400,detail=f"Owner error: {e}")@app.get("/items/{item_id}")defget_item(item_id:str,username:str=Depends(get_username)):ifitem_idnotindata:raiseHTTPException(status_code=404,detail="Item not found")item=data[item_id]ifitem["owner"]!=username:raiseOwnerError(username)returnitem
An alternative you could use to catch exceptions (and possibly also raise another HTTPException) is to create a Custom Exception Handler.
The sequence of execution is more or less like this diagram. Time flows from top to bottom. And each column is one of the parts interacting or executing code.
Info
Only one response will be sent to the client. It might be one of the error responses or it will be the response from the path operation.
After one of those responses is sent, no other response can be sent.
Tip
This diagram shows HTTPException, but you could also raise any other exception that you catch in a dependency with yield or with a Custom Exception Handler.
If you raise any exception, it will be passed to the dependencies with yield, including HTTPException, and then again to the exception handlers. If there's no exception handler for that exception, it will then be handled by the default internal ServerErrorMiddleware, returning a 500 HTTP status code, to let the client know that there was an error in the server.
Dependencies with yield, HTTPException and Background Tasks¶
Warning
You most probably don't need these technical details, you can skip this section and continue below.
These details are useful mainly if you were using a version of FastAPI prior to 0.106.0 and used resources from dependencies with yield in background tasks.
Before FastAPI 0.106.0, raising exceptions after yield was not possible, the exit code in dependencies with yield was executed after the response was sent, so Exception Handlers would have already run.
This was designed this way mainly to allow using the same objects "yielded" by dependencies inside of background tasks, because the exit code would be executed after the background tasks were finished.
Nevertheless, as this would mean waiting for the response to travel through the network while unnecessarily holding a resource in a dependency with yield (for example a database connection), this was changed in FastAPI 0.106.0.
Tip
Additionally, a background task is normally an independent set of logic that should be handled separately, with its own resources (e.g. its own database connection).
So, this way you will probably have cleaner code.
If you used to rely on this behavior, now you should create the resources for background tasks inside the background task itself, and use internally only data that doesn't depend on the resources of dependencies with yield.
For example, instead of using the same database session, you would create a new database session inside of the background task, and you would obtain the objects from the database using this new session. And then instead of passing the object from the database as a parameter to the background task function, you would pass the ID of that object and then obtain the object again inside the background task function.