-
Notifications
You must be signed in to change notification settings - Fork 19
Description
Expected Behavior
The Debug Toolbar should initialize without errors and should render the HTML/JS content of the toolbar, with it docked to the right of the screen and collapsible.
Current Behavior
The application renders a 500 Error when the FastAPI app is up via Uvicorn.
Possible Solution
The KeyError is due to a 3rd party module dependency having incomplete/missing Metadata, particularly the name value for the application.
The best solution for these edge cases is to implement the get function for accessing a value via a key name instead of using square brackets. This will allow the empty value to pass through instead of raising the error.
Steps to reproduce
It is difficult to ascertain the precise conditions for when this error will arise (since the module name is not provided due to missing metadata), but the particular case may be when building comprehensive applications with larger requirements. My existing core requirements are below, as captured in a .in file.
aiofiles
aiomysql
celery
fastapi
fastapi-restful
fastcrud
flower
greenlet
gunicorn; platform_system != 'Windows'
httpx
httpx[socks]
httpx-html
html5lib
hypercorn; platform_system == 'Windows'
itsdangerous
jinjax
loguru
lxml
lxml[html_clean]
python-dateutil
python-decouple
python-slugify
psycopg
pydantic-ai[examples]
pytz
redis
simplejson
sqlalchemy_mixins
sqlmodel
sqlmodel-crud-utilities @ git+https://github.com/fsecada01/[email protected]
typing-inspect
uvicorn
xmljson
xmltodict
The steps are below.
- Create a virtual environment (e.g.:
uv venv .venv) - Install requirements (e.g.:
uv pip sync requirements.txt) - Instantiate a minimal build FastAPI build
- Include
DebugToolbarMiddlein the app viaadd_middlewarefunction forappinstance - Run
python -m app.pyif the main app file includesif __name__ == '__main__':line or runuvicorn app:appfrom CLI
Content
Running:
- Windows 11
- Python 3.13
- UV
Detailed Description
The following error log appears when attempting to initialize the application.
INFO: 127.0.0.1:16788 - "GET / HTTP/1.1" 500 Internal Server Error
ERROR: Exception in ASGI application
+ Exception Group Traceback (most recent call last):
| File "C:\dev\python\interview_eval_project\highmark_agentic_ai\.venv\Lib\site-packages\starlette\middleware\base.py", line 187, in __call__
| response = await self.dispatch_func(request, call_next)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| File "C:\dev\python\interview_eval_project\highmark_agentic_ai\.venv\Lib\site-packages\debug_toolbar\middleware.py", line 84, in dispatch
| await toolbar.record_stats(response)
| File "C:\dev\python\interview_eval_project\highmark_agentic_ai\.venv\Lib\site-packages\debug_toolbar\toolbar.py", line 91, in record_stats
| async with create_task_group() as tg:
| ~~~~~~~~~~~~~~~~~^^
| File "C:\dev\python\interview_eval_project\highmark_agentic_ai\.venv\Lib\site-packages\anyio\_backends\_asyncio.py", line 767, in __aexit__
| raise BaseExceptionGroup(
| "unhandled errors in a TaskGroup", self._exceptions
| )
| ExceptionGroup: unhandled errors in a TaskGroup (1 sub-exception)
+-+---------------- 1 ----------------
| Traceback (most recent call last):
| File "C:\dev\python\interview_eval_project\highmark_agentic_ai\.venv\Lib\site-packages\uvicorn\protocols\http\h11_impl.py", line 403, in run_asgi
| result = await app( # type: ignore[func-returns-value]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| self.scope, self.receive, self.send
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| )
| ^
| File "C:\dev\python\interview_eval_project\highmark_agentic_ai\.venv\Lib\site-packages\uvicorn\middleware\proxy_headers.py", line 60, in __call__
| return await self.app(scope, receive, send)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| File "C:\dev\python\interview_eval_project\highmark_agentic_ai\.venv\Lib\site-packages\fastapi\applications.py", line 1054, in __call__
| await super().__call__(scope, receive, send)
| File "C:\dev\python\interview_eval_project\highmark_agentic_ai\.venv\Lib\site-packages\starlette\applications.py", line 113, in __call__
| await self.middleware_stack(scope, receive, send)
| File "C:\dev\python\interview_eval_project\highmark_agentic_ai\.venv\Lib\site-packages\starlette\middleware\errors.py", line 187, in __call__
| raise exc
| File "C:\dev\python\interview_eval_project\highmark_agentic_ai\.venv\Lib\site-packages\starlette\middleware\errors.py", line 165, in __call__
| await self.app(scope, receive, _send)
| File "C:\dev\python\interview_eval_project\highmark_agentic_ai\.venv\Lib\site-packages\starlette\middleware\base.py", line 185, in __call__
| with collapse_excgroups():
| ~~~~~~~~~~~~~~~~~~^^
| File "C:\Python313\Lib\contextlib.py", line 162, in __exit__
| self.gen.throw(value)
| ~~~~~~~~~~~~~~^^^^^^^
| File "C:\dev\python\interview_eval_project\highmark_agentic_ai\.venv\Lib\site-packages\starlette\_utils.py", line 82, in collapse_excgroups
| raise exc
| File "C:\dev\python\interview_eval_project\highmark_agentic_ai\.venv\Lib\site-packages\debug_toolbar\panels\__init__.py", line 88, in record_stats
| stats = await self.generate_stats(request, response)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| File "C:\dev\python\interview_eval_project\highmark_agentic_ai\.venv\Lib\site-packages\debug_toolbar\panels\versions.py", line 26, in generate_stats
| packages = sorted(
| metadata.distributions(),
| key=lambda dist: dist.metadata["name"].lower(),
| )
| File "C:\dev\python\interview_eval_project\highmark_agentic_ai\.venv\Lib\site-packages\debug_toolbar\panels\versions.py", line 28, in <lambda>
| key=lambda dist: dist.metadata["name"].lower(),
| ~~~~~~~~~~~~~^^^^^^^^
| File "C:\dev\python\interview_eval_project\highmark_agentic_ai\.venv\Lib\site-packages\importlib_metadata\_adapters.py", line 54, in __getitem__
| raise KeyError(item)
| KeyError: 'name'
+------------------------------------
During handling of the above exception, another exception occurred:
+ Exception Group Traceback (most recent call last):
| File "C:\dev\python\interview_eval_project\highmark_agentic_ai\.venv\Lib\site-packages\starlette\_utils.py", line 76, in collapse_excgroups
| yield
| File "C:\dev\python\interview_eval_project\highmark_agentic_ai\.venv\Lib\site-packages\starlette\middleware\base.py", line 186, in __call__
| async with anyio.create_task_group() as task_group:
| ~~~~~~~~~~~~~~~~~~~~~~~^^
| File "C:\dev\python\interview_eval_project\highmark_agentic_ai\.venv\Lib\site-packages\anyio\_backends\_asyncio.py", line 767, in __aexit__
| raise BaseExceptionGroup(
| "unhandled errors in a TaskGroup", self._exceptions
| )
| ExceptionGroup: unhandled errors in a TaskGroup (1 sub-exception)
+-+---------------- 1 ----------------
| Exception Group Traceback (most recent call last):
| File "C:\dev\python\interview_eval_project\highmark_agentic_ai\.venv\Lib\site-packages\starlette\middleware\base.py", line 187, in __call__
| response = await self.dispatch_func(request, call_next)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| File "C:\dev\python\interview_eval_project\highmark_agentic_ai\.venv\Lib\site-packages\debug_toolbar\middleware.py", line 84, in dispatch
| await toolbar.record_stats(response)
| File "C:\dev\python\interview_eval_project\highmark_agentic_ai\.venv\Lib\site-packages\debug_toolbar\toolbar.py", line 91, in record_stats
| async with create_task_group() as tg:
| ~~~~~~~~~~~~~~~~~^^
| File "C:\dev\python\interview_eval_project\highmark_agentic_ai\.venv\Lib\site-packages\anyio\_backends\_asyncio.py", line 767, in __aexit__
| raise BaseExceptionGroup(
| "unhandled errors in a TaskGroup", self._exceptions
| )
| ExceptionGroup: unhandled errors in a TaskGroup (1 sub-exception)
+-+---------------- 1 ----------------
| Traceback (most recent call last):
| File "C:\dev\python\interview_eval_project\highmark_agentic_ai\.venv\Lib\site-packages\uvicorn\protocols\http\h11_impl.py", line 403, in run_asgi
| result = await app( # type: ignore[func-returns-value]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| self.scope, self.receive, self.send
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| )
| ^
| File "C:\dev\python\interview_eval_project\highmark_agentic_ai\.venv\Lib\site-packages\uvicorn\middleware\proxy_headers.py", line 60, in __call__
| return await self.app(scope, receive, send)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| File "C:\dev\python\interview_eval_project\highmark_agentic_ai\.venv\Lib\site-packages\fastapi\applications.py", line 1054, in __call__
| await super().__call__(scope, receive, send)
| File "C:\dev\python\interview_eval_project\highmark_agentic_ai\.venv\Lib\site-packages\starlette\applications.py", line 113, in __call__
| await self.middleware_stack(scope, receive, send)
| File "C:\dev\python\interview_eval_project\highmark_agentic_ai\.venv\Lib\site-packages\starlette\middleware\errors.py", line 187, in __call__
| raise exc
| File "C:\dev\python\interview_eval_project\highmark_agentic_ai\.venv\Lib\site-packages\starlette\middleware\errors.py", line 165, in __call__
| await self.app(scope, receive, _send)
| File "C:\dev\python\interview_eval_project\highmark_agentic_ai\.venv\Lib\site-packages\starlette\middleware\base.py", line 185, in __call__
| with collapse_excgroups():
| ~~~~~~~~~~~~~~~~~~^^
| File "C:\Python313\Lib\contextlib.py", line 162, in __exit__
| self.gen.throw(value)
| ~~~~~~~~~~~~~~^^^^^^^
| File "C:\dev\python\interview_eval_project\highmark_agentic_ai\.venv\Lib\site-packages\starlette\_utils.py", line 82, in collapse_excgroups
| raise exc
| File "C:\dev\python\interview_eval_project\highmark_agentic_ai\.venv\Lib\site-packages\debug_toolbar\panels\__init__.py", line 88, in record_stats
| stats = await self.generate_stats(request, response)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| File "C:\dev\python\interview_eval_project\highmark_agentic_ai\.venv\Lib\site-packages\debug_toolbar\panels\versions.py", line 26, in generate_stats
| packages = sorted(
| metadata.distributions(),
| key=lambda dist: dist.metadata["name"].lower(),
| )
| File "C:\dev\python\interview_eval_project\highmark_agentic_ai\.venv\Lib\site-packages\debug_toolbar\panels\versions.py", line 28, in <lambda>
| key=lambda dist: dist.metadata["name"].lower(),
| ~~~~~~~~~~~~~^^^^^^^^
| File "C:\dev\python\interview_eval_project\highmark_agentic_ai\.venv\Lib\site-packages\importlib_metadata\_adapters.py", line 54, in __getitem__
| raise KeyError(item)
| KeyError: 'name'
+------------------------------------
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "C:\dev\python\interview_eval_project\highmark_agentic_ai\.venv\Lib\site-packages\uvicorn\protocols\http\h11_impl.py", line 403, in run_asgi
result = await app( # type: ignore[func-returns-value]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
self.scope, self.receive, self.send
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
)
^
File "C:\dev\python\interview_eval_project\highmark_agentic_ai\.venv\Lib\site-packages\uvicorn\middleware\proxy_headers.py", line 60, in __call__
return await self.app(scope, receive, send)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\dev\python\interview_eval_project\highmark_agentic_ai\.venv\Lib\site-packages\fastapi\applications.py", line 1054, in __call__
await super().__call__(scope, receive, send)
File "C:\dev\python\interview_eval_project\highmark_agentic_ai\.venv\Lib\site-packages\starlette\applications.py", line 113, in __call__
await self.middleware_stack(scope, receive, send)
File "C:\dev\python\interview_eval_project\highmark_agentic_ai\.venv\Lib\site-packages\starlette\middleware\errors.py", line 187, in __call__
raise exc
File "C:\dev\python\interview_eval_project\highmark_agentic_ai\.venv\Lib\site-packages\starlette\middleware\errors.py", line 165, in __call__
await self.app(scope, receive, _send)
File "C:\dev\python\interview_eval_project\highmark_agentic_ai\.venv\Lib\site-packages\starlette\middleware\base.py", line 185, in __call__
with collapse_excgroups():
~~~~~~~~~~~~~~~~~~^^
File "C:\Python313\Lib\contextlib.py", line 162, in __exit__
self.gen.throw(value)
~~~~~~~~~~~~~~^^^^^^^
File "C:\dev\python\interview_eval_project\highmark_agentic_ai\.venv\Lib\site-packages\starlette\_utils.py", line 82, in collapse_excgroups
raise exc
File "C:\dev\python\interview_eval_project\highmark_agentic_ai\.venv\Lib\site-packages\debug_toolbar\panels\__init__.py", line 88, in record_stats
stats = await self.generate_stats(request, response)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\dev\python\interview_eval_project\highmark_agentic_ai\.venv\Lib\site-packages\debug_toolbar\panels\versions.py", line 26, in generate_stats
packages = sorted(
metadata.distributions(),
key=lambda dist: dist.metadata["name"].lower(),
)
File "C:\dev\python\interview_eval_project\highmark_agentic_ai\.venv\Lib\site-packages\debug_toolbar\panels\versions.py", line 28, in <lambda>
key=lambda dist: dist.metadata["name"].lower(),
~~~~~~~~~~~~~^^^^^^^^
File "C:\dev\python\interview_eval_project\highmark_agentic_ai\.venv\Lib\site-packages\importlib_metadata\_adapters.py", line 54, in __getitem__
raise KeyError(item)
KeyError: 'name'Possible Implementation
The below code seems to fix this issue:
async def generate_stats(self, request: Request, response: Response) -> Stats:
dists = {d.metadata.get("name", None): d for d in
metadata.distributions()}
packages = sorted(
dists,
key=lambda dist: dist.lower() if dist else "",
)
return {"packages": packages}