sgl-project/sglang · error · TypeError

expected mapping, got {type(value).__name__}

Error message

expected mapping, got {type(value).__name__}

What it means

_as_mapping normalizes tool definitions, tool calls, and messages to a Mapping before rendering. It accepts a Mapping or any object with model_dump() returning a Mapping; anything else (str, int, list, None) raises TypeError.

Source

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


def _expect_role(message: Mapping[str, Any]) -> str:
    role = message.get("role")
    if role not in ROLE_MESSAGE_TOKENS:
        raise ValueError(
            f"unsupported Inkling message role {role!r}; expected one of {sorted(ROLE_MESSAGE_TOKENS)}"
        )
    return str(role)


def _as_mapping(value: Any) -> Mapping[str, Any]:
    if isinstance(value, Mapping):
        return value
    if hasattr(value, "model_dump"):
        dumped = value.model_dump()
        if isinstance(dumped, Mapping):
            return dumped
    raise TypeError(f"expected mapping, got {type(value).__name__}")


def _canonical_json(value: Any) -> str:
    return json.dumps(
        _sort_json(value),
        ensure_ascii=False,
        allow_nan=False,
        separators=(",", ":"),
    )


def _sort_json(value: Any) -> Any:
    if isinstance(value, Mapping):
        return {str(key): _sort_json(value[key]) for key in sorted(value)}
    if isinstance(value, Sequence) and not isinstance(value, (str, bytes, bytearray)):
        return [_sort_json(item) for item in value]
    return value

View on GitHub (pinned to 0132848349)

Solutions

  1. Parse JSON strings back to dicts before sending: json.loads(s)
  2. Pass plain dicts or pydantic v2 models (which support model_dump)
  3. Wrap lists in a proper mapping structure

Example fix

# before
tool_calls=[json.dumps({"name":"f","arguments":{}})]
# after
tool_calls=[{"name":"f","arguments":{}}]  # keep as dict
Defensive patterns

Strategy: type-guard

Validate before calling

from collections.abc import Mapping
for m in messages:
    for tc in m.get("tool_calls") or []:
        assert isinstance(tc, Mapping) or hasattr(tc, "model_dump"), type(tc)

Type guard

def tool_call_ok(tc): return isinstance(tc, Mapping) or hasattr(tc, "model_dump")

Prevention

When it happens

Trigger: Passing a tool_call as a JSON string instead of a dict, e.g. {"role":"assistant","tool_calls":["{\"name\":\"f\"}"]}, or a tool definition as a list.

Common situations: Clients that json.dumps tool calls for transport and forget to parse them back; passing OpenAI SDK objects without model_dump support (older pydantic v1 style).

Related errors


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