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.

Dependency injection failure for unhashable types

See original GitHub issue

Example

Suppose you run the following script

export MY_PREFIX_PASSWORD=hello

and then

from fastapi import FastAPI

app = FastAPI()

class MySettings(BaseSettings):
    password: SecretStr
    base_url: AnyHttpUrl = "https://www.google.com"
    localdownload_dir: str = "~/mydir-import"

    class Config:
        env_prefix = "my_prefix"

def get_settings() -> MySettings:
    return MySettings()

   
@app.get("/")
def read_root(settings:MySettings = Depends(get_settings)):
    return {"Hello": "World"}

Description

When you invoke via curl the rest endpoint, you get the following failure:

File "/venv/lib/python3.7/site-packages/uvicorn/protocols/http/httptools_impl.py", line 390, in run_asgi result = await app(self.scope, self.receive, self.send) File "/venv/lib/python3.7/site-packages/uvicorn/middleware/proxy_headers.py", line 45, in __call__ return await self.app(scope, receive, send) File "/venv/lib/python3.7/site-packages/fastapi/applications.py", line 179, in __call__ await super().__call__(scope, receive, send) File "/venv/lib/python3.7/site-packages/starlette/applications.py", line 111, in __call__ await self.middleware_stack(scope, receive, send) File "/venv/lib/python3.7/site-packages/starlette/middleware/errors.py", line 181, in __call__ raise exc from None File "/venv/lib/python3.7/site-packages/starlette/middleware/errors.py", line 159, in __call__ await self.app(scope, receive, _send) File "/venv/lib/python3.7/site-packages/starlette/exceptions.py", line 82, in __call__ raise exc from None File "/venv/lib/python3.7/site-packages/starlette/exceptions.py", line 71, in __call__ await self.app(scope, receive, sender) File "/venv/lib/python3.7/site-packages/starlette/routing.py", line 566, in __call__ await route.handle(scope, receive, send) File "/venv/lib/python3.7/site-packages/starlette/routing.py", line 227, in handle await self.app(scope, receive, send) File "/venv/lib/python3.7/site-packages/starlette/routing.py", line 41, in app response = await func(request) File "/venv/lib/python3.7/site-packages/fastapi/routing.py", line 176, in app dependency_overrides_provider=dependency_overrides_provider, File "/venv/lib/python3.7/site-packages/fastapi/dependencies/utils.py", line 552, in solve_dependencies solved = await run_in_threadpool(call, **sub_values) File "/venv/lib/python3.7/site-packages/starlette/concurrency.py", line 34, in run_in_threadpool return await loop.run_in_executor(None, func, *args) File "/usr/local/lib/python3.7/concurrent/futures/thread.py", line 57, in run result = self.fn(*self.args, **self.kwargs) TypeError: unhashable type: 'MySettings'

Environment

  • OS: [e.g. Linux / Windows / macOS]: MACOS
  • FastAPI Version = “0.61.0”
  • Python version: 3.7.3

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Reactions:1
  • Comments:12 (1 by maintainers)

github_iconTop GitHub Comments

7reactions
cbenzcommented, Jan 21, 2021

This documentation section shows that we can use a dependency with Depends which uses @lru_cache. I followed this docs and had the same problem described by this issue.

Should the docs be updated to remove the usage of @lru_cache or can it be useful in some cases?

4reactions
escapedcommented, Feb 9, 2021

Just ran into the same issue. Looks like pydantic does not implement a __hash__() method for its models as of now: https://github.com/samuelcolvin/pydantic/pull/1881. ~So, I guess we should update the documentation, or do I miss something?~ (edit: see next comment)

I guess, in general, it makes sense to document the use of lru_cache, as otherwise, the dependency generator is called for every request instead of just once. Additionally, it might be useful to explicitly state that lru_cache only works for hashable objects.

Anyway, we can work around that issue for now by either let fastapi call the method multiple times, implement a __hash__() method for the Settings class or implement a custom caching mechanism, eg.

def get_settings() -> config.Settings:
    cache = getattr(get_settings, "__cached", None)
    if not cache:
        settings = config.Settings()
        get_settings.__cache = settings
    return get_settings.__cache
Read more comments on GitHub >

github_iconTop Results From Across the Web

Python: TypeError: unhashable type: 'list' - Net-Informations.Com
This error shows that the my_dict key [1,2,3] is List and List is not a hashable type in Python . Dictionary keys must...
Read more >
How to Handle Unhashable Type List Exceptions in Python
The standard way to solve this issue is to cast a list to a tuple, which is a hashable data type.
Read more >
tiangolo/fastapi - Gitter
Is FastAPI dependency injection system is only limited for use in API endpoints? ... @dmontagu The error is "TypeError: unhashable type: 'dict'".
Read more >
Bug descriptions — spotbugs 4.7.3 documentation
When debugging tests that fail due to bad casts, it may be more useful to observe the output of the resulting ClassCastException which...
Read more >
OpenStack - Launchpad Bugs
#1473363 GlusterFS CI for Cinder fails for encrypted volumes tests ... introspection with ERROR ironic_inspector.process TypeError: unhashable type: 'list'.
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