PrefectHQ/fastmcp · warning · ValidationError

{str(e)}

Error message

{str(e)}

What it means

Argument-validation failures (pydantic ValidationErrors raised while validating call arguments against the tool's parameter schema) are re-raised as fastmcp ValidationError with log_level WARNING so middleware and error taxonomy treat them as client errors. The raised message is the stringified pydantic error listing which arguments failed validation.

Source

Thrown at fastmcp_slim/fastmcp/tools/function_tool.py:439

                        f"Tool '{self.name}' timed out after {self.timeout}s. "
                        f"Consider using task=True for long-running operations. "
                        f"See https://gofastmcp.com/servers/tasks"
                    )
                    raise MCPError(
                        code=-32000,
                        message=f"Tool '{self.name}' execution timed out after {self.timeout}s",
                    ) from None
            else:
                result = await self._execute(
                    type_adapter, exec_is_async, arguments, strict=strict
                )
        except PydanticValidationError as e:
            # Body errors are re-raised as _ToolBodyError, so a bare pydantic
            # ValidationError here is an argument-validation failure (a bad call).
            # Convert it to fastmcp's ValidationError so the middleware chain and
            # downstream error taxonomy (e.g. Sentry filters) can treat it as a
            # client error rather than a server bug.
            raise ValidationError(str(e), log_level=logging.WARNING) from e
        except _ToolBodyError as e:
            # The tool's own body raised a pydantic ValidationError. Surface the
            # original so it is treated as a server-side error, hiding the
            # internal sentinel while preserving the error's own chained cause.
            original = e.__cause__
            assert original is not None
            raise original from original.__cause__

        return result

    async def _execute(
        self,
        type_adapter: TypeAdapter[Any],
        exec_is_async: bool,
        arguments: dict[str, Any],
        *,
        strict: bool = False,
    ) -> Any:

View on GitHub (pinned to 1f02114297)

Solutions

  1. Fix the caller's arguments to match the tool's parameter schema (types, required fields)
  2. Re-fetch the tool schema (list_tools) after any signature change and regenerate the call
  3. Validate arguments client-side with the tool's input schema before invoking

Example fix

// before
await client.call_tool("add", {"a": "1", "b": 2})   # a: str not int
// after
await client.call_tool("add", {"a": 1, "b": 2})
Defensive patterns

Strategy: validation

Validate before calling

# validate args against the tool's input schema before calling
def args_match_schema(args: dict, input_schema: dict) -> bool:
    import jsonschema
    try:
        jsonschema.validate(args, input_schema)
        return True
    except jsonschema.ValidationError:
        return False

Try / catch

from fastmcp.exceptions import ValidationError
try:
    result = await client.call_tool('my_tool', args)
except ValidationError as e:
    logger.warning('bad tool arguments: %s', e)
    args = fix_args_from_message(str(e), args)
    result = await client.call_tool('my_tool', args)

Prevention

When it happens

Trigger: Calling a tool with wrong argument types (e.g. string where int expected), missing required parameters, or extra unknown parameters — anything failing the tool's input schema validation in _run_body.

Common situations: LLM clients generating malformed arguments; API changes to a tool's signature while callers cache old schemas; passing JSON numbers as strings; forgetting to coerce nested models.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of PrefectHQ/fastmcp@1f02114297 (2026-08-29). Data as JSON: /api/errors/d7afc74a877c9b56. Report an issue: GitHub.