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.

[BUG] Async class method dependency raises a ValueError

See original GitHub issue

Describe the bug If you use an async class method as a dependency, a ValueError is thrown. It doesn’t happen for a non-async method.

Complete error: ValueError: [KeyError(<class 'coroutine'>), TypeError("'coroutine' object is not iterable"), TypeError('vars() argument must have __dict__ attribute')] (at fastapi/encoders.py:106)

To Reproduce

from fastapi import Depends, FastAPI
from starlette.requests import Request

class DependencyClass:
    async def async_dep(self, request: Request):
        return True

    def sync_dep(self, request: Request):
        return True

app = FastAPI()
dependency = DependencyClass()

# Error
@app.get('/async-dep')
def async_dep(r=Depends(dependency.async_dep)):
    return r

# Everything is fine
@app.get('/sync-dep')
def sync_dep(r=Depends(dependency.sync_dep)):
    return r

Expected behavior The async class method dependency should be called and its return value injected.

Environment:

  • OS: macOS
  • FastAPI Version: 0.42.0
  • Python version: 3.7.2

Additional context I believe the issue comes from here:

https://github.com/tiangolo/fastapi/blob/65536cbf63318d111bf608960378d651b6c1596a/fastapi/dependencies/utils.py#L353-L359

Indeed, inspect.isfunction(call) will return False in case of a class method. Hence, it is sent to run_in_threadpool, which never awaits the coroutine, and we end up trying to serialize it instead of its result (hence the ValueError).

Changing the check by:

if inspect.isfunction(call) or inspect.ismethod(call):

solves the issue. I can make a PR with the fix and unit tests if it helps.

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Comments:6 (6 by maintainers)

github_iconTop GitHub Comments

1reaction
tiangolocommented, Apr 10, 2020

Thanks for the help here everyone! 👏 🙇

Thanks for reporting back and closing the issue @frankie567 👍 And thanks for the PR/fix! 🎉

1reaction
dmontagucommented, Nov 4, 2019

This makes sense to me; @frankie567 I think it’s worth a PR.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Python [FastApi] - propagate Exception thrown to base class
I have implemented JWT encoder/decoder methods which I run as a dependency on my route. I made use of the CustomHttpBearer method and...
Read more >
Finding and reporting an asyncio bug in Python 3.10
It works by calling the lock._get_loop() method, but only if it exists—so even though that's an undocumented internal method this should be safe ......
Read more >
Async IO in Python: A Complete Walkthrough
A function that you introduce with async def is a coroutine. It may use await , return , or yield , but all...
Read more >
Handling Errors - FastAPI
The benefit of raising an exception over return ing a value will be more evident in the section about Dependencies and Security. In...
Read more >
What's New In Python 3.11 — Python 3.11.1 documentation
PEP 657: Fine-grained error locations in tracebacks ... Common use cases include alternative constructors provided as classmethod s, and __enter__() methods ...
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