{"record":{"id":"a3d3efda43067190","repo":"PrefectHQ/fastmcp","slug":"invalid-json-in-tool-arguments-for-func-name","errorCode":null,"errorMessage":"Invalid JSON in tool arguments for '{func.name}': {func.arguments}","messagePattern":"Invalid JSON in tool arguments for '(.+?)': (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"fastmcp_slim/fastmcp/client/sampling/handlers/openai.py","lineNumber":491,"sourceCode":"        # Build content list\n        content: list[TextContent | ToolUseContent] = []\n\n        # Add text content if present\n        if message.content:\n            content.append(TextContent(type=\"text\", text=message.content))\n\n        # Add tool calls if present\n        if message.tool_calls:\n            for tool_call in message.tool_calls:\n                # Skip non-function tool calls\n                if not hasattr(tool_call, \"function\"):\n                    continue\n                func = tool_call.function\n                # Parse the arguments JSON string\n                try:\n                    arguments = json.loads(func.arguments)  # type: ignore[union-attr]  # ty:ignore[unresolved-attribute]\n                except json.JSONDecodeError as e:\n                    raise ValueError(\n                        f\"Invalid JSON in tool arguments for \"\n                        f\"'{func.name}': {func.arguments}\"  # type: ignore[union-attr]  # ty:ignore[unresolved-attribute]\n                    ) from e\n\n                content.append(\n                    ToolUseContent(\n                        type=\"tool_use\",\n                        id=tool_call.id,\n                        name=func.name,  # type: ignore[union-attr]  # ty:ignore[unresolved-attribute]\n                        input=arguments,\n                    )\n                )\n\n        # Must have at least some content\n        if not content:\n            raise ValueError(\"No content in response from completion\")\n\n        return CreateMessageResultWithTools(","sourceCodeStart":473,"sourceCodeEnd":509,"githubUrl":"https://github.com/PrefectHQ/fastmcp/blob/1f021142978e0861cd910c8df4e8074bc7cf3978/fastmcp_slim/fastmcp/client/sampling/handlers/openai.py#L473-L509","documentation":"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.","triggerScenarios":"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.","commonSituations":"Very low max_tokens cutting off argument JSON; complex/deeply nested schemas the model fumbles; streaming interruptions; models prone to invalid JSON escapes.","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."],"exampleFix":"// before\nresult = await handler(messages, params_with_max_tokens=50)\n// after\ntry:\n    result = await handler(messages, params)\nexcept ValueError as e:\n    if 'Invalid JSON in tool arguments' in str(e):\n        result = await handler(messages, replace(params, maxTokens=2048))\n    else:\n        raise","handlingStrategy":"try-catch","validationCode":"import json\ndef assert_tool_args_parseable(completion):\n    for ch in completion.choices:\n        for tc in (ch.message.tool_calls or []):\n            if hasattr(tc, 'function') and tc.function.arguments:\n                json.loads(tc.function.arguments)","typeGuard":"def is_valid_tool_args(tc) -> bool:\n    import json\n    f = getattr(tc, 'function', None)\n    if not f or not f.arguments:\n        return False\n    try:\n        json.loads(f.arguments)\n        return True\n    except json.JSONDecodeError:\n        return False","tryCatchPattern":"try:\n    result = await sampling_handler(messages, params)\nexcept ValueError as e:\n    if 'Invalid JSON in tool arguments' in str(e):\n        logger.warning('Bad tool args: %s', e)\n        result = await sampling_handler(messages, params)  # retry; or repair JSON\n    else:\n        raise","preventionTips":["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"],"tags":["openai","sampling","json","tool-calls","truncation"],"backgroundTag":"invalid-tool-arguments-json","analyzedSha":"1f021142978e0861cd910c8df4e8074bc7cf3978","analyzedAt":"2026-08-29T14:31:16.082Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}