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
- Fix the caller's arguments to match the tool's parameter schema (types, required fields)
- Re-fetch the tool schema (list_tools) after any signature change and regenerate the call
- 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
- Refresh cached tool schemas after server updates
- Coerce JSON strings to numbers where schemas expect numbers
- Validate LLM-generated arguments against input_schema before invoking
- Keep tool signatures stable; version instead of mutating
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
- The API key is empty
- The Horizon API key is invalid
- mode must be 'legacy', 'auto', or one of {list(MODERN_PROTOC
- The 'verify' parameter is only supported for HTTP transports
- a custom cache store requires CacheConfig.target_id for Fast
AI-assisted analysis of PrefectHQ/fastmcp@1f02114297 (2026-08-29).
Data as JSON: /api/errors/d7afc74a877c9b56.
Report an issue: GitHub.