@@ -814,6 +814,38 @@ async def test_max_tool_fatal_error_emits_analytics_event(self, read_taxonomy_mo
814814 self .assertIn ("organization" , groups )
815815 self .assertIn ("project" , groups )
816816
817+ @patch ("ee.hogai.tools.read_taxonomy.ReadTaxonomyTool._run_impl" )
818+ async def test_max_tool_error_groups_call_works_in_async_context (self , read_taxonomy_mock ):
819+ """Test that groups() call in error handler works in async context without SynchronousOnlyOperation."""
820+ read_taxonomy_mock .side_effect = MaxToolFatalError ("Test error" )
821+
822+ # Re-fetch the user from DB to simulate production behavior where
823+ # current_organization is NOT pre-loaded (it's lazy-loaded)
824+ fresh_user = await User .objects .aget (id = self .user .id )
825+
826+ node = _create_agent_tools_node (self .team , fresh_user )
827+ state = AssistantState (
828+ messages = [
829+ AssistantMessage (
830+ content = "Using tool that will fail" ,
831+ id = "test-id" ,
832+ tool_calls = [
833+ AssistantToolCall (id = "tool-123" , name = "read_taxonomy" , args = {"query" : {"kind" : "events" }})
834+ ],
835+ )
836+ ],
837+ root_tool_call_id = "tool-123" ,
838+ )
839+
840+ # This config triggers the posthoganalytics.capture path
841+ config = RunnableConfig (configurable = {"distinct_id" : "test-user-123" })
842+
843+ # This must not raise SynchronousOnlyOperation in the groups() call
844+ result = await node .arun (state , config )
845+
846+ # Should complete without error
847+ self .assertIsInstance (result , PartialAssistantState )
848+
817849 @patch ("ee.hogai.tools.read_taxonomy.ReadTaxonomyTool._run_impl" )
818850 async def test_max_tool_retryable_error_returns_error_with_retry_hint (self , read_taxonomy_mock ):
819851 """Test that MaxToolRetryableError includes retry hint for adjusted inputs."""
0 commit comments