sgl-project/sglang · error · TypeError

tool call function arguments must decode to an object

Error message

tool call function arguments must decode to an object

What it means

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.

Source

Thrown at python/sglang/srt/parser/inkling_renderer.py:326

            }
        )
    return _canonical_json(tool_specs)


def _tool_call_name_and_args(tool_call_value: Any) -> tuple[str, Mapping[str, Any]]:
    tool_call = _as_mapping(tool_call_value)
    function = _as_mapping(tool_call.get("function", {}))
    name = function.get("name")
    if not isinstance(name, str):
        raise TypeError("tool call function name must be a string")

    raw_args = function.get("arguments") or {}
    if isinstance(raw_args, str):
        args = json.loads(raw_args) if raw_args else {}
    else:
        args = raw_args
    if not isinstance(args, Mapping):
        raise TypeError("tool call function arguments must decode to an object")
    return name, args


def _tool_call_json(name: str, args: Mapping[str, Any]) -> str:
    name_json = json.dumps(name, ensure_ascii=False, allow_nan=False)
    return f'{{"name":{name_json},"args":{_canonical_json(args)}}}'

View on GitHub (pinned to 0132848349)

Solutions

  1. Ensure arguments decodes to a JSON object (dict), e.g. '{"query": "..."}' not '["..."]' or '"text"'
  2. If your tool genuinely takes positional args, wrap them in an object like {"args": [...]}
  3. Log the raw arguments value to spot double-encoding or list-shaped payloads

Example fix

// before
call = {"function": {"name": "f", "arguments": "[1, 2]"}}
// after
call = {"function": {"name": "f", "arguments": "{\"args\": [1, 2]}"}}
Defensive patterns

Strategy: validation

Validate before calling

import json
from collections.abc import Mapping

def args_are_object(fn):
    raw = fn.get("arguments") or {}
    args = json.loads(raw) if isinstance(raw, str) and raw else raw
    return isinstance(args, Mapping)

Type guard

def has_object_args(tc: Any) -> TypeGuard[dict]:
    fn = tc.get("function") if isinstance(tc, dict) else None
    if not isinstance(fn, dict):
        return False
    raw = fn.get("arguments") or {}
    args = json.loads(raw) if isinstance(raw, str) and raw else raw
    return isinstance(args, Mapping)

Try / catch

try:
    render_inkling_messages(msgs)
except TypeError as e:
    if "arguments" in str(e):
        normalize_tool_call_args(msgs)  # wrap scalars/lists into {"args": value}
    else:
        raise

Prevention

When it happens

Trigger: 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.

Common situations: Models emitting array-valued arguments, upstream parsers storing positional args as a list, or double-encoded JSON where decoding yields a scalar.

Related errors


AI-assisted analysis of sgl-project/sglang@0132848349 (2026-08-28). Data as JSON: /api/errors/95232cba0bd3dfd3. Report an issue: GitHub.