PrefectHQ/fastmcp · error · ValueError
Invalid JSON in tool arguments for '{func.name}': {func.argu
Error message
Invalid JSON in tool arguments for '{func.name}': {func.arguments} What it means
OpenAI returns tool call arguments as a JSON-encoded string. The handler json.loads() that string to build ToolUseContent; if the model emitted malformed JSON (truncated output, invalid escapes, prose instead of JSON), JSONDecodeError is caught and re-raised as this ValueError including the function name and raw arguments.
Source
Thrown at fastmcp_slim/fastmcp/client/sampling/handlers/openai.py:491
# Build content list
content: list[TextContent | ToolUseContent] = []
# Add text content if present
if message.content:
content.append(TextContent(type="text", text=message.content))
# Add tool calls if present
if message.tool_calls:
for tool_call in message.tool_calls:
# Skip non-function tool calls
if not hasattr(tool_call, "function"):
continue
func = tool_call.function
# Parse the arguments JSON string
try:
arguments = json.loads(func.arguments) # type: ignore[union-attr] # ty:ignore[unresolved-attribute]
except json.JSONDecodeError as e:
raise ValueError(
f"Invalid JSON in tool arguments for "
f"'{func.name}': {func.arguments}" # type: ignore[union-attr] # ty:ignore[unresolved-attribute]
) from e
content.append(
ToolUseContent(
type="tool_use",
id=tool_call.id,
name=func.name, # type: ignore[union-attr] # ty:ignore[unresolved-attribute]
input=arguments,
)
)
# Must have at least some content
if not content:
raise ValueError("No content in response from completion")
return CreateMessageResultWithTools(View on GitHub (pinned to 1f02114297)
Solutions
- Increase max_tokens so the arguments JSON is not truncated.
- Retry the request — argument JSON quality varies per generation.
- Simplify the tool's input_schema (fewer required/nested fields) to make valid JSON more likely.
- Catch ValueError, log func.arguments, and either repair the JSON or re-ask the model.
Example fix
// before
result = await handler(messages, params_with_max_tokens=50)
// after
try:
result = await handler(messages, params)
except ValueError as e:
if 'Invalid JSON in tool arguments' in str(e):
result = await handler(messages, replace(params, maxTokens=2048))
else:
raise Defensive patterns
Strategy: try-catch
Validate before calling
import json
def assert_tool_args_parseable(completion):
for ch in completion.choices:
for tc in (ch.message.tool_calls or []):
if hasattr(tc, 'function') and tc.function.arguments:
json.loads(tc.function.arguments) Type guard
def is_valid_tool_args(tc) -> bool:
import json
f = getattr(tc, 'function', None)
if not f or not f.arguments:
return False
try:
json.loads(f.arguments)
return True
except json.JSONDecodeError:
return False Try / catch
try:
result = await sampling_handler(messages, params)
except ValueError as e:
if 'Invalid JSON in tool arguments' in str(e):
logger.warning('Bad tool args: %s', e)
result = await sampling_handler(messages, params) # retry; or repair JSON
else:
raise Prevention
- Raise maxTokens to avoid truncated argument JSON
- Simplify tool input_schema (fewer/nested required fields)
- Prefer models known for reliable JSON tool calling
- Log raw func.arguments to enable repair/replay
When it happens
Trigger: A tool call in message.tool_calls has function.arguments that is not valid JSON — commonly from finish_reason='length' truncating the JSON mid-string, or the model hallucinating non-JSON arguments.
Common situations: Very low max_tokens cutting off argument JSON; complex/deeply nested schemas the model fumbles; streaming interruptions; models prone to invalid JSON escapes.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Unsupported content type for OpenAI: {type(item).__name__}
- No content in response from completion (finish_reason={finis
- Unsupported image MIME type for OpenAI: {content.mime_type!r
- Unsupported audio MIME type for OpenAI: {content.mime_type!r
- ImageContent/AudioContent is only supported in user messages
AI-assisted analysis of PrefectHQ/fastmcp@1f02114297 (2026-08-29).
Data as JSON: /api/errors/a3d3efda43067190.
Report an issue: GitHub.