PrefectHQ/fastmcp · error · RuntimeError
forward() can only be called within a transformed tool
Error message
forward() can only be called within a transformed tool
What it means
forward() delegates to the original (pre-transform) tool by reading a context variable set only while a transformed tool executes. Calling it outside that context (plain function, test, direct call) finds _current_tool unset and raises RuntimeError.
Source
Thrown at fastmcp_slim/fastmcp/tools/tool_transform.py:71
For example, if the parent tool has args `x` and `y`, but the transformed
tool has args `a` and `b`, and an `transform_args` was provided that maps `x` to
`a` and `y` to `b`, then `forward(a=1, b=2)` will call the parent tool with
`x=1` and `y=2`.
Args:
**kwargs: Arguments to forward to the parent tool (using transformed names).
Returns:
The ToolResult from the parent tool execution.
Raises:
RuntimeError: If called outside a transformed tool context.
TypeError: If provided arguments don't match the transformed schema.
"""
tool = _current_tool.get()
if tool is None:
raise RuntimeError("forward() can only be called within a transformed tool")
# Use the forwarding function that handles mapping
return await tool.forwarding_fn(**kwargs)
async def forward_raw(**kwargs: Any) -> ToolResult:
"""Forward directly to parent tool without transformation.
This function bypasses all argument transformation and validation, calling the parent
tool directly with the provided arguments. Use this when you need to call the parent
with its original parameter names and structure.
For example, if the parent tool has args `x` and `y`, then `forward_raw(x=1,
y=2)` will call the parent tool with `x=1` and `y=2`.
Args:
**kwargs: Arguments to pass directly to the parent tool (using original names).
View on GitHub (pinned to 1f02114297)
Solutions
- Call forward() only inside the custom function passed to add_confirmation/custom in a tool transform
- In tests, exercise forward() through the transformed tool (invoke the transformed tool) rather than calling forward directly
- If you need the original tool's result outside a transform, call the original tool directly instead of using forward
Example fix
// before
def helper():
return await forward(x=1) # RuntimeError outside transform
// after
async def custom_fn(ctx, x):
return await forward(x=x) # inside transform_tool(..., custom_fn=custom_fn) Defensive patterns
Strategy: validation
Validate before calling
def require_transform_context():
from fastmcp.tools.tool_transform import _current_tool
if _current_tool.get() is None:
raise RuntimeError('forward() called outside a transformed tool') Try / catch
try:
result = await forward(x=1)
except RuntimeError as e:
if 'within a transformed tool' in str(e):
result = await original_tool.run({'x': 1}) # call original directly Prevention
- Only call forward()/forward_raw() inside custom transform functions
- Test transforms by invoking the transformed tool end-to-end, not forward() directly
- Keep forward() calls in leaf helper code that only runs under the transform context
When it happens
Trigger: Calling forward(...) or forward_raw(...) from a normal function, module-level code, or a test without running inside a transformed tool's custom function (custom/custom_fn set the context; transform_function-wrapped code does not).
Common situations: Unit-testing helper functions that call forward() in isolation; refactoring a custom transform function so part of it runs outside the wrapped execution; importing forward into unrelated code.
Related errors
- forward_raw() can only be called within a transformed tool
- No access token available. Cannot perform OBO exchange.
- FastMCP instance is no longer available
- Unexpected CreateTaskResult: Context calls should not have t
- request_id is not available because the MCP session has not
AI-assisted analysis of PrefectHQ/fastmcp@1f02114297 (2026-08-29).
Data as JSON: /api/errors/026d17d113aa6782.
Report an issue: GitHub.