sgl-project/sglang · error · ValueError

{field_name} must be a JSON object

Error message

{field_name} must be a JSON object

What it means

After successfully parsing the extra_params JSON, the API requires it to be a JSON object (dict). Arrays, strings, numbers, or null JSON values ('[1,2]', '"x"', '5') raise ValueError('{field_name} must be a JSON object') -> HTTP 400.

Source

Thrown at python/sglang/multimodal_gen/runtime/entrypoints/action/api.py:98

    if not isinstance(value, str):
        return value
    if not value.strip():
        return None
    try:
        return json.loads(value)
    except Exception:
        return value


def _parse_extra_params(value: Any, field_name: str) -> dict[str, Any]:
    if value in (None, ""):
        return {}
    try:
        parsed = json.loads(value) if isinstance(value, str) else value
    except (json.JSONDecodeError, TypeError) as exc:
        raise ValueError(f"{field_name} is not valid JSON") from exc
    if not isinstance(parsed, dict):
        raise ValueError(f"{field_name} must be a JSON object")
    return flatten_extra_params(dict(parsed))


def _is_form_upload(value: Any) -> bool:
    return callable(getattr(value, "read", None)) and hasattr(value, "filename")


def _is_probably_video_upload(value: Any) -> bool:
    content_type = (getattr(value, "content_type", "") or "").lower()
    if content_type.startswith("video/"):
        return True
    filename = getattr(value, "filename", None)
    if not filename:
        return False
    filename = str(filename).split("?", 1)[0].split("#", 1)[0]
    return os.path.splitext(filename)[1].lower() in _ACTION_VIDEO_EXTENSIONS

View on GitHub (pinned to 0132848349)

Solutions

  1. Change the value to a JSON object: '{"key": "value"}'
  2. If you need a list, nest it under a key: '{"items": [...]}'

Example fix

// before
extra_params=["top_k", 5]

// after
extra_params={"top_k": 5}
Defensive patterns

Strategy: type-guard

Validate before calling

import json
def validate_extra_params(s: str) -> dict:
    parsed = json.loads(s)
    if not isinstance(parsed, dict):
        raise TypeError("extra_params must encode a JSON object")
    return parsed

Type guard

def is_json_object(s: str) -> bool:
    try:
        return isinstance(json.loads(s), dict)
    except (json.JSONDecodeError, TypeError):
        return False

Prevention

When it happens

Trigger: Passing extra_params='[1, 2, 3]' or '"temperature=0.7"' (a JSON string) or 'null' in the multipart form.

Common situations: Wrapping params in a JSON array; double-encoding so the outer value parses to a scalar or list instead of a dict.

Related errors


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