{"record":{"id":"c7194e370996ebe0","repo":"PrefectHQ/fastmcp","slug":"forward-raw-can-only-be-called-within-a-transfor","errorCode":null,"errorMessage":"forward_raw() can only be called within a transformed tool","messagePattern":"forward_raw\\(\\) 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":98,"sourceCode":"    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\n    Returns:\n        The ToolResult from the parent tool execution.\n\n    Raises:\n        RuntimeError: If called outside a transformed tool context.\n    \"\"\"\n    tool = _current_tool.get()\n    if tool is None:\n        raise RuntimeError(\"forward_raw() can only be called within a transformed tool\")\n\n    return await tool.parent_tool.run(kwargs)\n\n\n@dataclass(kw_only=True)\nclass ArgTransform:\n    \"\"\"Configuration for transforming a parent tool's argument.\n\n    This class allows fine-grained control over how individual arguments are transformed\n    when creating a new tool from an existing one. You can rename arguments, change their\n    descriptions, add default values, or hide them from clients while passing constants.\n\n    Attributes:\n        name: New name for the argument. Use None to keep original name, or ... for no change.\n        description: New description for the argument. Use None to remove description, or ... for no change.\n        default: New default value for the argument. Use ... for no change.\n        default_factory: Callable that returns a default value. Cannot be used with default.\n        type: New type for the argument. Use ... for no change.","sourceCodeStart":80,"sourceCodeEnd":116,"githubUrl":"https://github.com/PrefectHQ/fastmcp/blob/1f021142978e0861cd910c8df4e8074bc7cf3978/fastmcp_slim/fastmcp/tools/tool_transform.py#L80-L116","documentation":"forward_raw() forwards a call to the parent (untransformed) tool, but it only works inside the replacement function of a transformed tool, which establishes a context variable via a ContextVar. If _current_tool is not set — i.e. forward_raw was called from arbitrary code or a plain test — the library raises RuntimeError to prevent forwarding with no valid parent tool.","triggerScenarios":"Calling forward_raw() (or a forward wrapper built on it) from a regular function not registered via ToolTransform.from_tool; importing and invoking forward_raw in unit tests without the transformed-tool context; storing the forwarding function and calling it later after the transform context has exited.","commonSituations":"Writing custom replacement functions for transformed tools and accidentally calling forward_raw outside the closure passed to transform_tool/from_tool; copy-pasting forward_raw into application code; tests that call the forwarding function directly instead of through the transformed tool.","solutions":["Call forward_raw() only inside the function you pass as the replacement to a tool transformation (from_tool / transform tool flow).","If you need the parent tool behavior elsewhere, call the parent tool directly instead of forward_raw().","In tests, invoke the transformed tool (which sets up the context) rather than calling forward_raw out of context; or use the library's test harness that establishes the transformed-tool context."],"exampleFix":"// before\ndef my_helper(x):\n    return forward_raw(x)  # RuntimeError: no transformed-tool context\n\n// after\nasync def my_replacement(x):\n    # passed to from_tool(...) as the custom replacement function\n    result = await forward_raw(x)\n    return result * 2","handlingStrategy":"validation","validationCode":"from fastmcp.tools.tool_transform import _current_tool\n\ndef forward_raw_available() -> bool:\n    return _current_tool.get() is not None","typeGuard":null,"tryCatchPattern":"try:\n    result = await forward_raw(**kwargs)\nexcept RuntimeError as e:\n    if \"transformed tool\" in str(e):\n        raise RuntimeError(\"forward_raw must be called inside a tool-transform replacement function\") from e\n    raise","preventionTips":["Only call forward_raw from within the custom function passed to from_tool.","Never import forward_raw into application code or tests that run outside a transformed tool.","Test forwarding behavior by invoking the transformed tool itself."],"tags":["python","tool-transform","context"],"backgroundTag":"api-called-outside-context","analyzedSha":"1f021142978e0861cd910c8df4e8074bc7cf3978","analyzedAt":"2026-08-29T14:31:16.082Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}