Skip to content

Conversation

@stevapple
Copy link
Contributor

@stevapple stevapple commented Nov 26, 2025

Running async tool under sync context (require settings.allow_tool_async_sync_conversion) is handled by Tool._run_async_in_sync. If there's no running event loop, we used to run the coroutine directly when handling the RuntimeError raised by asyncio.get_running_loop(). This resulted in exception chaining, where the error raised by the tool will be chained with the RuntimeError raised by asyncio. Since the result will be passed to the LM as tool call result, such behavior is regarded as unnecessary leak of implementation detail, and will diverge the result of running with async and in sync. Move the real call outside of the except block will resolve the problem.

Before

Execution error in retrieve: 
Traceback (most recent call last):
  File ".venv\Lib\site-packages\dspy\adapters\types\tool.py", line 167, in _run_async_in_sync
    loop = asyncio.get_running_loop()
RuntimeError: no running event loop

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File ".venv\Lib\site-packages\dspy\predict\react.py", line 111, in forward
    trajectory[f"observation_{idx}"] = self.tools[pred.next_tool_name](**pred.next_tool_args)
                                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^
  File ".venv\Lib\site-packages\dspy\utils\callback.py", line 326, in sync_wrapper
    return fn(instance, *args, **kwargs)
  File ".venv\Lib\site-packages\dspy\adapters\types\tool.py", line 179, in __call__
    return self._run_async_in_sync(result)
           ~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^
  File ".venv\Lib\site-packages\dspy\adapters\types\tool.py", line 169, in _run_async_in_sync
    return asyncio.run(coroutine)
           ~~~~~~~~~~~^^^^^^^^^^^
  File "\Lib\asyncio\runners.py", line 195, in run
    return runner.run(main)
           ~~~~~~~~~~^^^^^^
ValueError: Invalid request

After

Execution error in retrieve: 
Traceback (most recent call last):
  File ".venv\Lib\site-packages\dspy\predict\react.py", line 111, in forward
    trajectory[f"observation_{idx}"] = self.tools[pred.next_tool_name](**pred.next_tool_args)
                                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^
  File ".venv\Lib\site-packages\dspy\utils\callback.py", line 326, in sync_wrapper
    return fn(instance, *args, **kwargs)
  File ".venv\Lib\site-packages\dspy\adapters\types\tool.py", line 182, in __call__
    return self._run_async_in_sync(result)
           ~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^
  File ".venv\Lib\site-packages\dspy\adapters\types\tool.py", line 173, in _run_async_in_sync
    return asyncio.run(coroutine)
           ~~~~~~~~~~~^^^^^^^^^^^
  File "\Lib\asyncio\runners.py", line 195, in run
    return runner.run(main)
           ~~~~~~~~~~^^^^^^
ValueError: Invalid request

…text

Running async tool under sync context (require `settings.allow_tool_async_sync_conversion`) is handled by `Tool._run_async_in_sync`. If there's no running event loop, we used to run the coroutine directly when handling the `RuntimeError` raised by `asyncio.get_running_loop()`. This resulted in exception chaining, where the error raised by the tool will be chained with the `RuntimeError` raised by `asyncio`. Since the result will be passed to the LM as tool call result, such behavior is regarded as unnecessary leak of implementation detail, and will diverge the result of running with `async` and in sync. Move the real call outside of the `except` block will resolve the problem.

## Before

```
Execution error in retrieve: 
Traceback (most recent call last):
  File ".venv\Lib\site-packages\dspy\adapters\types\tool.py", line 167, in _run_async_in_sync
    loop = asyncio.get_running_loop()
RuntimeError: no running event loop

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File ".venv\Lib\site-packages\dspy\predict\react.py", line 111, in forward
    trajectory[f"observation_{idx}"] = self.tools[pred.next_tool_name](**pred.next_tool_args)
                                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^
  File ".venv\Lib\site-packages\dspy\utils\callback.py", line 326, in sync_wrapper
    return fn(instance, *args, **kwargs)
  File ".venv\Lib\site-packages\dspy\adapters\types\tool.py", line 176, in __call__
    result = self.func(**parsed_kwargs)
  File "src\retrieval\tool.py", line 169, in retrieve
    result = run_request(kwargs)
             ~~~~~~~~~~~^^^^^^^^
ValueError: Invalid request
```

## After

```
Execution error in retrieve: 
Traceback (most recent call last):
  File ".venv\Lib\site-packages\dspy\predict\react.py", line 111, in forward
    trajectory[f"observation_{idx}"] = self.tools[pred.next_tool_name](**pred.next_tool_args)
                                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^
  File ".venv\Lib\site-packages\dspy\utils\callback.py", line 326, in sync_wrapper
    return fn(instance, *args, **kwargs)
  File ".venv\Lib\site-packages\dspy\adapters\types\tool.py", line 176, in __call__
    result = self.func(**parsed_kwargs)
  File "src\retrieval\tool.py", line 169, in retrieve
    result = run_request(kwargs)
             ~~~~~~~~~~~^^^^^^^^
ValueError: Invalid request
```
Copy link
Collaborator

@chenmoneygithub chenmoneygithub left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the fix!

@chenmoneygithub chenmoneygithub merged commit d42f29e into stanfordnlp:main Nov 26, 2025
12 checks passed
@stevapple stevapple deleted the patch-1 branch November 28, 2025 02:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants