question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Yield dependency doesn't get http exceptions being raised.

See original GitHub issue

Describe the bug

HTTP exceptions are not ~raised~ propagated inside a dependency which encapsulates the yield in a try except statement. Only custom exceptions are ~raised~ propagated if I understand correctly.

To Reproduce

  1. Create a main.py with:

    from fastapi import Depends, FastAPI, HTTPException
    
    app = FastAPI()
    
    
    def new_db_session():
        try:
            yield
    
        except Exception:
            print("rollback")
    
        else:
            print("commit")
    
        finally:
            print("close")
    
    
    @app.get("/exception")
    def get_exception(db=Depends(new_db_session)):
        raise Exception()
    
    
    @app.get("/http_exception")
    def get_exception(db=Depends(new_db_session)):
        raise HTTPException(status_code=400, detail="invalid request")
    
  2. run app using uvicorn main:app

  3. curl http://127.0.0.1:8000/exception; app prints:

    INFO:     127.0.0.1:50069 - "GET /exception HTTP/1.1" 500 Internal Server Error
    rollback
    close
    
  4. curl http://127.0.0.1:8000/http_exception; app prints:

    INFO:     127.0.0.1:50072 - "GET /http_exception HTTP/1.1" 400 Bad Request
    commit
    close
    

Expected behavior

HTTP Exception should be ~raised~ propagated inside the dependency try except statement.

Environment

  • OS: Darwin Kernel Version 19.0.0: Thu Oct 17 16:17:15 PDT 2019; root:xnu-6153.41.3~29/RELEASE_X86_64 x86_64 i386 MacBookPro13,1 Darwin
  • FastAPI Version: 0.46.0
  • Python version: Python 3.7.3

Additional context

  • PR: Dependencies with yield (used as context managers)
  • From @dmontagu in #570:

    @cjw296 As implemented, it would require some care to ensure teardown was done in a guaranteed order. I think it would currently amount to constructing a consistent “teardown” dependency. But I think in most cases, you would be able to just build a single dependency that sets everything up in order, and tears it down in order, and then to build other dependencies on top of that. For example, handling your use case:

    def db_contextmanager():
        conn = connect_to_db()
        t = conn.transaction()
        try:
             yield conn, t
            t.commit()
        except:
            t.rollback()
         conn.close()
    
    def get_connection(conn_t = Depends(db_contextmanager)):
        conn, t = conn_t
        return conn
    
    def get_transaction(conn_t = Depends(db_contextmanager)):
        conn, t = conn_t
        return t
    
    def endpoint(conn = Depends(get_connection)):
        # Do something with the connection
        pass
    

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Reactions:11
  • Comments:17 (10 by maintainers)

github_iconTop GitHub Comments

4reactions
dmontagucommented, Feb 17, 2020

@tiangolo these docs are incredible 👏👏

3reactions
dmontagucommented, Mar 3, 2020

I think this behavior is explained in the new docs.

It sounds to me like your question is closer to “how can I detect whether an error was raised during the execution of the yield statement, even if it was handled by an exception handler”. Unfortunately, as of now, I think the answer is just that you can’t. So maybe this issue is better classified as a feature request than a bug.

For what it’s worth, I do think this is a reasonable feature request, though I’m not sure 1) what a good API for it would be, or 2) whether there are any common problems that could be caused by “double-handling” the exception like that.

That said, I would be in favor of having exceptions raised in contextmanager dependencies even if they were also handled by request-handling code, as it would make it easier to perform proper cleanup (e.g., rolling back a transaction when using a contextmanager-based sqlalchemy session dependency).

Read more comments on GitHub >

github_iconTop Results From Across the Web

Dependencies with yield - FastAPI
So, if you raise an HTTPException after the yield , the default (or any custom) exception handler that catches HTTPException s and returns...
Read more >
typescript - How to catch exception correctly from http.request()?
If res.json() raises an error because it could not parse the JSON data, _serverError will not get a Response object, hence the reason...
Read more >
Complete Guide to Exception Handling in Spring Boot
Spring Boot's Default Exception Handling Mechanism. Let's say we have a controller named ProductController whose getProduct(...) method is ...
Read more >
Futures and error handling | Dart
Everything you wanted to know about handling errors and exceptions when ... no new error is produced within then() , catchError() 's callback...
Read more >
Chapter 11. Exceptions and Conditions
If p returns and the exception is continuable, p is reinstated as the current exception handler. (raise (condition (make-error) (make-message-condition "no ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found