{"record":{"id":"be71cae1c44bf3a1","repo":"ComposioHQ/composio","slug":"tool-arguments-were-provided-as-a-string-that-is-n","errorCode":null,"errorMessage":"Tool arguments were provided as a string that is not valid JSON: {e}","messagePattern":"Tool arguments were provided as a string that is not valid JSON: (.+?)","errorType":"validation","errorClass":"InvalidParams","httpStatus":null,"severity":"error","filePath":"python/composio/utils/shared.py","lineNumber":93,"sourceCode":"    - A string is JSON-parsed; an empty / whitespace-only string becomes ``{}``.\n    - Anything that does not resolve to a dict (lists, primitives, unparseable\n      strings, JSON that parses to a non-object) raises :class:`InvalidParams`.\n\n    :param arguments: Raw arguments as received from the model / framework.\n    :return: The normalized arguments as a dict.\n    :raises InvalidParams: If the arguments cannot be resolved to a dict.\n    \"\"\"\n    if arguments is None:\n        return {}\n\n    if isinstance(arguments, str):\n        stripped = arguments.strip()\n        if not stripped:\n            return {}\n        try:\n            parsed = json.loads(stripped)\n        except json.JSONDecodeError as e:\n            raise InvalidParams(\n                f\"Tool arguments were provided as a string that is not valid JSON: {e}\"\n            ) from e\n        return _as_dict(parsed)\n\n    return _as_dict(arguments)\n\n\ndef _as_dict(value: t.Any) -> t.Dict[str, t.Any]:\n    if isinstance(value, dict):\n        return value\n    raise InvalidParams(\n        f\"Tool arguments must resolve to an object, received {type(value).__name__}\"\n    )\n\n\ndef validate_and_serialize_tool_arguments(\n    args_schema: t.Type[BaseModel],\n    arguments: t.Dict[str, t.Any],","sourceCodeStart":75,"sourceCodeEnd":111,"githubUrl":"https://github.com/ComposioHQ/composio/blob/64b1b85502b1beeb2379e6c9e8bf1104504fa637/python/composio/utils/shared.py#L75-L111","documentation":"normalize_tool_arguments accepts tool arguments as a JSON string (as produced by many LLM providers), but json.loads failed on the non-empty string. The InvalidParams error wraps the json.JSONDecodeError so you can see the exact parse position.","triggerScenarios":"Passing arguments='{'query': 'x'}' (single quotes, invalid JSON), a truncated response, a string with a leading/trailing code fence or prose, or a Python-repr dict (\"{'a': 1}\") straight from an LLM or str(dict).","commonSituations":"Models emitting Python-dict syntax instead of strict JSON; tool-call arguments streamed and truncated; markdown fences around JSON; double-encoded JSON ('\\\"{\\\\\"a\\\\\":1}\\\"') from a provider quirk; ad-hoc scripts passing str(payload).","solutions":["Pass a dict when you have structured data: normalize_tool_arguments({...}) instead of a string","If you must handle strings, pre-validate with json.loads and repair common issues (single quotes, fences, truncation) before calling","Enable provider-side JSON/structured output so the model emits valid JSON","Log the raw string on failure — the wrapped JSONDecodeError position pinpoints the breakage"],"exampleFix":"# before\nresult = tool.run(arguments=\"{'query': 'x'}\")\n# after\nresult = tool.run(arguments='{\"query\": \"x\"}')\n# or better\nresult = tool.run(arguments={\"query\": \"x\"})","handlingStrategy":"try-catch","validationCode":"import json\ndef parse_args_string(s):\n    if not isinstance(s, str): return s\n    s = s.strip()\n    if not s: return {}\n    try: return json.loads(s)\n    except json.JSONDecodeError: return None  # caller repairs or rejects","typeGuard":"def is_json_object_string(s: str) -> bool:\n    try:\n        return isinstance(json.loads(s), dict)\n    except (json.JSONDecodeError, TypeError):\n        return False","tryCatchPattern":"from composio.exceptions import InvalidParams\ntry:\n    args = normalize_tool_arguments(raw)\nexcept InvalidParams as e:\n    raw = repair_json_like(raw)  # fix quotes/fences, or ask model to retry\n    args = normalize_tool_arguments(raw)","preventionTips":["Pass dicts, not strings, whenever you have structured data","Enable provider structured-output/JSON mode for tool calls","Strip markdown fences and whitespace from LLM output before parsing"],"tags":["tool-arguments","json","llm-output","invalid-params"],"backgroundTag":"invalid-json-tool-arguments","analyzedSha":"64b1b85502b1beeb2379e6c9e8bf1104504fa637","analyzedAt":"2026-08-28T15:39:33.623Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}