sgl-project/sglang · error · ValueError

{field_name} is not valid JSON

Error message

{field_name} is not valid JSON

What it means

_parse_extra_params parses string fields (e.g. extra_params in a multipart form) as JSON; a malformed JSON string raises ValueError('{field_name} is not valid JSON'), returned as HTTP 400. Non-JSON-serializable non-string types also trigger it via TypeError.

Source

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

def _parse_form_value(value: Any) -> Any:
    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. Fix the field to be a valid JSON object string, e.g. '{"top_k": 5}'
  2. Do not use query-string/form encoding (a=1&b=2) in this field; JSON-encode a dict instead
  3. Send the request as application/json body rather than multipart if possible, where params are already structured

Example fix

# before
extra_params=top_k=5;temperature=0.7

# after
extra_params={"top_k": 5, "temperature": 0.7}
Defensive patterns

Strategy: validation

Validate before calling

import json
def safe_extra_params(v):
    if v in (None, ""):
        return {}
    parsed = json.loads(v)
    assert isinstance(parsed, dict)
    return parsed  # send json.dumps(parsed) in the form field

Try / catch

try:
    resp = client.post(url, files=files)
    resp.raise_for_status()
except HTTPError:
    if "not valid JSON" in resp.text: fix_extra_params_string()
    else: raise

Prevention

When it happens

Trigger: Submitting a multipart action request where extra_params='{"top_k": ' (truncated) or 'top_k=5' (URL-encoded form syntax instead of JSON), or passing an unserializable object.

Common situations: Using form-style key=value strings where a JSON object is expected; smart quotes or trailing commas from copy-pasting; truncated request bodies.

Related errors


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