[🐛 Bug]: Incidents 'NoneType' object is not iterable
Describe the bug
Fresh installation using Postgresql throws errors inside the container when the incidents page has no records. I am still able to manually create an incident after which time the error is resolved.
This does not seem to actually impact the application it's just more noise that is being logged
To Reproduce Steps to reproduce the behavior:
- Install Keep using Postgres
- Click on
Incidents - Error.
Expected behavior Clean container logs
Log
[2024-12-09 13:33:10 +0000] [17] [ERROR] Exception in ASGI application
+ Exception Group Traceback (most recent call last):
| File "/venv/lib/python3.11/site-packages/starlette/_utils.py", line 87, in collapse_excgroups
| yield
| File "/venv/lib/python3.11/site-packages/starlette/middleware/base.py", line 190, in __call__
| async with anyio.create_task_group() as task_group:
| File "/venv/lib/python3.11/site-packages/anyio/_backends/_asyncio.py", line 680, in __aexit__
| raise BaseExceptionGroup(
| ExceptionGroup: unhandled errors in a TaskGroup (1 sub-exception)
+-+---------------- 1 ----------------
| Traceback (most recent call last):
| File "/venv/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py", line 407, in run_asgi
| result = await app( # type: ignore[func-returns-value]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| File "/venv/lib/python3.11/site-packages/uvicorn/middleware/proxy_headers.py", line 78, in __call__
| return await self.app(scope, receive, send)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| File "/venv/lib/python3.11/site-packages/fastapi/applications.py", line 1054, in __call__
| await super().__call__(scope, receive, send)
| File "/venv/lib/python3.11/site-packages/starlette/applications.py", line 123, in __call__
| await self.middleware_stack(scope, receive, send)
| File "/venv/lib/python3.11/site-packages/starlette/middleware/errors.py", line 186, in __call__
| raise exc
| File "/venv/lib/python3.11/site-packages/starlette/middleware/errors.py", line 164, in __call__
| await self.app(scope, receive, _send)
| File "/venv/lib/python3.11/site-packages/opentelemetry/instrumentation/asgi/__init__.py", line 596, in __call__
| await self.app(scope, otel_receive, otel_send)
| File "/venv/lib/python3.11/site-packages/starlette/middleware/base.py", line 189, in __call__
| with collapse_excgroups():
| File "/usr/local/lib/python3.11/contextlib.py", line 158, in __exit__
| self.gen.throw(typ, value, traceback)
| File "/venv/lib/python3.11/site-packages/starlette/_utils.py", line 93, in collapse_excgroups
| raise exc
| File "/venv/lib/python3.11/site-packages/starlette/middleware/base.py", line 191, in __call__
| response = await self.dispatch_func(request, call_next)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| File "/venv/lib/python3.11/site-packages/keep/api/observability.py", line 89, in __call__
| response = await call_next(request)
| ^^^^^^^^^^^^^^^^^^^^^^^^
| File "/venv/lib/python3.11/site-packages/starlette/middleware/base.py", line 165, in call_next
| raise app_exc
| File "/venv/lib/python3.11/site-packages/starlette/middleware/base.py", line 151, in coro
| await self.app(scope, receive_or_disconnect, send_no_error)
| File "/venv/lib/python3.11/site-packages/starlette/middleware/base.py", line 189, in __call__
| with collapse_excgroups():
| File "/usr/local/lib/python3.11/contextlib.py", line 158, in __exit__
| self.gen.throw(typ, value, traceback)
| File "/venv/lib/python3.11/site-packages/starlette/_utils.py", line 93, in collapse_excgroups
| raise exc
| File "/venv/lib/python3.11/site-packages/starlette/middleware/base.py", line 191, in __call__
| response = await self.dispatch_func(request, call_next)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| File "/venv/lib/python3.11/site-packages/keep/api/middlewares.py", line 54, in dispatch
| response = await call_next(request)
| ^^^^^^^^^^^^^^^^^^^^^^^^
| File "/venv/lib/python3.11/site-packages/starlette/middleware/base.py", line 165, in call_next
| raise app_exc
| File "/venv/lib/python3.11/site-packages/starlette/middleware/base.py", line 151, in coro
| await self.app(scope, receive_or_disconnect, send_no_error)
| File "/venv/lib/python3.11/site-packages/starlette/middleware/cors.py", line 83, in __call__
| await self.app(scope, receive, send)
| File "/venv/lib/python3.11/site-packages/starlette/middleware/gzip.py", line 24, in __call__
| await responder(scope, receive, send)
| File "/venv/lib/python3.11/site-packages/starlette/middleware/gzip.py", line 44, in __call__
| await self.app(scope, receive, self.send_with_gzip)
| File "/venv/lib/python3.11/site-packages/starlette_context/middleware/raw_middleware.py", line 92, in __call__
| await self.app(scope, receive, send_wrapper)
| File "/venv/lib/python3.11/site-packages/starlette/middleware/exceptions.py", line 62, in __call__
| await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send)
| File "/venv/lib/python3.11/site-packages/starlette/_exception_handler.py", line 64, in wrapped_app
| raise exc
| File "/venv/lib/python3.11/site-packages/starlette/_exception_handler.py", line 53, in wrapped_app
| await app(scope, receive, sender)
| File "/venv/lib/python3.11/site-packages/starlette/routing.py", line 758, in __call__
| await self.middleware_stack(scope, receive, send)
| File "/venv/lib/python3.11/site-packages/starlette/routing.py", line 778, in app
| await route.handle(scope, receive, send)
| File "/venv/lib/python3.11/site-packages/starlette/routing.py", line 299, in handle
| await self.app(scope, receive, send)
| File "/venv/lib/python3.11/site-packages/starlette/routing.py", line 79, in app
| await wrap_app_handling_exceptions(app, request)(scope, receive, send)
| File "/venv/lib/python3.11/site-packages/starlette/_exception_handler.py", line 64, in wrapped_app
| raise exc
| File "/venv/lib/python3.11/site-packages/starlette/_exception_handler.py", line 53, in wrapped_app
| await app(scope, receive, sender)
| File "/venv/lib/python3.11/site-packages/starlette/routing.py", line 74, in app
| response = await func(request)
| ^^^^^^^^^^^^^^^^^^^
| File "/venv/lib/python3.11/site-packages/fastapi/routing.py", line 299, in app
| raise e
| File "/venv/lib/python3.11/site-packages/fastapi/routing.py", line 294, in app
| raw_response = await run_endpoint_function(
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| File "/venv/lib/python3.11/site-packages/fastapi/routing.py", line 193, in run_endpoint_function
| return await run_in_threadpool(dependant.call, **values)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| File "/venv/lib/python3.11/site-packages/starlette/concurrency.py", line 42, in run_in_threadpool
| return await anyio.to_thread.run_sync(func, *args)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| File "/venv/lib/python3.11/site-packages/anyio/to_thread.py", line 56, in run_sync
| return await get_async_backend().run_sync_in_worker_thread(
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| File "/venv/lib/python3.11/site-packages/anyio/_backends/_asyncio.py", line 2177, in run_sync_in_worker_thread
| return await future
| ^^^^^^^^^^^^
| File "/venv/lib/python3.11/site-packages/anyio/_backends/_asyncio.py", line 859, in run
| result = context.run(func, *args)
| ^^^^^^^^^^^^^^^^^^^^^^^^
| File "/venv/lib/python3.11/site-packages/keep/api/routes/incidents.py", line 103, in get_incidents_meta
| meta = get_incidents_meta_for_tenant(tenant_id=tenant_id)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| File "/venv/lib/python3.11/site-packages/keep/api/core/db.py", line 3058, in get_incidents_meta_for_tenant
| "assignees": list(filter(bool, results.assignees)),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| TypeError: 'NoneType' object is not iterable
+------------------------------------
Hey @a-chartier! I'm here to help you with any bugs, questions, or contributions you have for the project. Let's squash those bugs together!
The error you're encountering is due to the get_incidents_meta_for_tenant function attempting to iterate over a NoneType object when there are no incidents in the database. This happens because the function is trying to process fields like assignees that might be None when there are no records.
The function is designed to handle such cases by returning an empty dictionary if the query results are None. However, it seems that this check might not be functioning correctly in your setup with PostgreSQL.
To resolve this issue, ensure that the function correctly checks for None results before attempting to iterate over them. The function should include a check like this:
results = session.exec(query).one_or_none()
if not results:
return {}
This check ensures that if there are no incidents, the function returns an empty dictionary, preventing the TypeError from occurring [1]. If this check is already in place, there might be an issue with how the results are being processed or returned in your specific environment.
To continue talking to Dosu, mention @dosu.
Help Dosu learn! Give it feedback: Great Response | Irrelevant Answer | Incorrect Sources | Too Verbose | Hallucination | Other
thanks @a-chartier , will look!
@shahargl @a-chartier please, tale a look on PR https://github.com/keephq/keep/pull/2789 with the fix