{"record":{"id":"026d17d113aa6782","repo":"PrefectHQ/fastmcp","slug":"forward-can-only-be-called-within-a-transformed","errorCode":null,"errorMessage":"forward() can only be called within a transformed tool","messagePattern":"forward\\(\\) can only be called within a transformed tool","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"fastmcp_slim/fastmcp/tools/tool_transform.py","lineNumber":71,"sourceCode":"\n    For example, if the parent tool has args `x` and `y`, but the transformed\n    tool has args `a` and `b`, and an `transform_args` was provided that maps `x` to\n    `a` and `y` to `b`, then `forward(a=1, b=2)` will call the parent tool with\n    `x=1` and `y=2`.\n\n    Args:\n        **kwargs: Arguments to forward to the parent tool (using transformed names).\n\n    Returns:\n        The ToolResult from the parent tool execution.\n\n    Raises:\n        RuntimeError: If called outside a transformed tool context.\n        TypeError: If provided arguments don't match the transformed schema.\n    \"\"\"\n    tool = _current_tool.get()\n    if tool is None:\n        raise RuntimeError(\"forward() can only be called within a transformed tool\")\n\n    # Use the forwarding function that handles mapping\n    return await tool.forwarding_fn(**kwargs)\n\n\nasync def forward_raw(**kwargs: Any) -> ToolResult:\n    \"\"\"Forward directly to parent tool without transformation.\n\n    This function bypasses all argument transformation and validation, calling the parent\n    tool directly with the provided arguments. Use this when you need to call the parent\n    with its original parameter names and structure.\n\n    For example, if the parent tool has args `x` and `y`, then `forward_raw(x=1,\n    y=2)` will call the parent tool with `x=1` and `y=2`.\n\n    Args:\n        **kwargs: Arguments to pass directly to the parent tool (using original names).\n","sourceCodeStart":53,"sourceCodeEnd":89,"githubUrl":"https://github.com/PrefectHQ/fastmcp/blob/1f021142978e0861cd910c8df4e8074bc7cf3978/fastmcp_slim/fastmcp/tools/tool_transform.py#L53-L89","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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"],"exampleFix":"// before\ndef helper():\n    return await forward(x=1)  # RuntimeError outside transform\n// after\nasync def custom_fn(ctx, x):\n    return await forward(x=x)  # inside transform_tool(..., custom_fn=custom_fn)","handlingStrategy":"validation","validationCode":"def require_transform_context():\n    from fastmcp.tools.tool_transform import _current_tool\n    if _current_tool.get() is None:\n        raise RuntimeError('forward() called outside a transformed tool')","typeGuard":null,"tryCatchPattern":"try:\n    result = await forward(x=1)\nexcept RuntimeError as e:\n    if 'within a transformed tool' in str(e):\n        result = await original_tool.run({'x': 1})  # call original directly","preventionTips":["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"],"tags":["python","tool-transform","context","runtime-error"],"backgroundTag":"missing-execution-context","analyzedSha":"1f021142978e0861cd910c8df4e8074bc7cf3978","analyzedAt":"2026-08-29T14:31:16.082Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}