{"record":{"id":"95232cba0bd3dfd3","repo":"sgl-project/sglang","slug":"tool-call-function-arguments-must-decode-to-an-obj","errorCode":null,"errorMessage":"tool call function arguments must decode to an object","messagePattern":"tool call function arguments must decode to an object","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"python/sglang/srt/parser/inkling_renderer.py","lineNumber":326,"sourceCode":"            }\n        )\n    return _canonical_json(tool_specs)\n\n\ndef _tool_call_name_and_args(tool_call_value: Any) -> tuple[str, Mapping[str, Any]]:\n    tool_call = _as_mapping(tool_call_value)\n    function = _as_mapping(tool_call.get(\"function\", {}))\n    name = function.get(\"name\")\n    if not isinstance(name, str):\n        raise TypeError(\"tool call function name must be a string\")\n\n    raw_args = function.get(\"arguments\") or {}\n    if isinstance(raw_args, str):\n        args = json.loads(raw_args) if raw_args else {}\n    else:\n        args = raw_args\n    if not isinstance(args, Mapping):\n        raise TypeError(\"tool call function arguments must decode to an object\")\n    return name, args\n\n\ndef _tool_call_json(name: str, args: Mapping[str, Any]) -> str:\n    name_json = json.dumps(name, ensure_ascii=False, allow_nan=False)\n    return f'{{\"name\":{name_json},\"args\":{_canonical_json(args)}}}'\n","sourceCodeStart":308,"sourceCodeEnd":333,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/srt/parser/inkling_renderer.py#L308-L333","documentation":"Raised when a tool call's function.arguments field, after JSON decoding, is not a JSON object/Mapping. String arguments are json.loads-ed first; if the result is a list, number, string, or null, or if arguments was a non-string non-mapping value directly, this TypeError fires.","triggerScenarios":"tool_calls[i]['function']['arguments'] is a JSON string encoding a non-object like '\"[1,2]\"', '\"5\"', or arguments passed directly as a Python list [1,2] instead of a dict.","commonSituations":"Models emitting array-valued arguments, upstream parsers storing positional args as a list, or double-encoded JSON where decoding yields a scalar.","solutions":["Ensure arguments decodes to a JSON object (dict), e.g. '{\"query\": \"...\"}' not '[\"...\"]' or '\"text\"'","If your tool genuinely takes positional args, wrap them in an object like {\"args\": [...]}","Log the raw arguments value to spot double-encoding or list-shaped payloads"],"exampleFix":"// before\ncall = {\"function\": {\"name\": \"f\", \"arguments\": \"[1, 2]\"}}\n// after\ncall = {\"function\": {\"name\": \"f\", \"arguments\": \"{\\\"args\\\": [1, 2]}\"}}","handlingStrategy":"validation","validationCode":"import json\nfrom collections.abc import Mapping\n\ndef args_are_object(fn):\n    raw = fn.get(\"arguments\") or {}\n    args = json.loads(raw) if isinstance(raw, str) and raw else raw\n    return isinstance(args, Mapping)","typeGuard":"def has_object_args(tc: Any) -> TypeGuard[dict]:\n    fn = tc.get(\"function\") if isinstance(tc, dict) else None\n    if not isinstance(fn, dict):\n        return False\n    raw = fn.get(\"arguments\") or {}\n    args = json.loads(raw) if isinstance(raw, str) and raw else raw\n    return isinstance(args, Mapping)","tryCatchPattern":"try:\n    render_inkling_messages(msgs)\nexcept TypeError as e:\n    if \"arguments\" in str(e):\n        normalize_tool_call_args(msgs)  # wrap scalars/lists into {\"args\": value}\n    else:\n        raise","preventionTips":["Emit arguments as a JSON object string, never a list/scalar","When parsing model output, wrap non-object argument payloads in {\"args\": ...}","Unit-test argument decoding against your model's actual output shapes"],"tags":["inkling","tool-calls","json-decode","arguments"],"backgroundTag":"invalid-tool-call-arguments","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T06:17:29.519Z"}