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_EXTENSIONSView on GitHub (pinned to 0132848349)
Solutions
- Fix the field to be a valid JSON object string, e.g. '{"top_k": 5}'
- Do not use query-string/form encoding (a=1&b=2) in this field; JSON-encode a dict instead
- 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
- Always build extra_params with json.dumps(dict), never hand-write the string
- Send structured JSON bodies instead of multipart when the client supports it
- Lint form fields in client integration tests
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
- runtime.response_format must be 'envelope' or 'raw'
- {field_name} must be a JSON object
- {detail}
- cache_dit_params must be a dict, got {type(raw).__name__}.
- Unknown cache_dit_params keys: {sorted(unknown)}. Valid keys
AI-assisted analysis of sgl-project/sglang@0132848349 (2026-08-28).
Data as JSON: /api/errors/18db6e3a1e0d7636.
Report an issue: GitHub.