sgl-project/sglang · error · ValueError
Kimi K3 tool property schemas must be JSON schemas
Error message
Kimi K3 tool property schemas must be JSON schemas
What it means
Each entry in tool.parameters.properties must be a property name (str) mapped to a JSON schema (bool for true/false schemas, or an object). A key or value of any other type (e.g. a schema given as a string or list) cannot be converted into a tag format, so the strict builder raises.
Source
Thrown at python/sglang/srt/function_call/kimik3_structural_tag.py:399
if not isinstance(properties, dict):
raise ValueError("Kimi K3 tool parameters 'properties' must be an object")
required = parameters.get("required", [])
if not isinstance(required, list) or not all(
isinstance(item, str) for item in required
):
raise ValueError("Kimi K3 tool parameters 'required' must be a string list")
required_set = set(required)
missing = required_set.difference(properties)
if missing:
raise ValueError(
f"Kimi K3 required parameters are missing schemas: {sorted(missing)!r}"
)
elements: List[Format] = []
for key, schema in properties.items():
if not isinstance(key, str) or not isinstance(schema, (bool, dict)):
raise ValueError("Kimi K3 tool property schemas must be JSON schemas")
argument = _known_argument_format(key, schema, parameters)
if argument is None:
if key in required_set:
raise ValueError(
f"Kimi K3 required parameter {key!r} accepts no values"
)
continue
elements.append(
argument if key in required_set else OptionalFormat(content=argument)
)
additional = parameters.get("additionalProperties", True)
if additional is True:
elements.append(StarFormat(content=_dynamic_argument_format(True, parameters)))
elif isinstance(additional, dict):
elements.append(
StarFormat(content=_dynamic_argument_format(additional, parameters))
)View on GitHub (pinned to 0132848349)
Solutions
- Wrap bare types into proper schema objects: {"type": "string"}
- Ensure every key is a string and every value is a dict or boolean
- Run the tool schema through a JSON Schema validator before passing it to the server
Example fix
// before
"properties": {"city": "string"}
// after
"properties": {"city": {"type": "string"}} Defensive patterns
Strategy: validation
Validate before calling
for k, v in params.get("properties", {}).items():
assert isinstance(k, str) and isinstance(v, (bool, dict)), f"bad property {k}" Type guard
def valid_property_schemas(params: dict) -> bool:
return all(
isinstance(k, str) and isinstance(v, (bool, dict))
for k, v in params.get("properties", {}).items()
) Try / catch
try:
build_tag(tools)
except ValueError as e:
if "must be JSON schemas" in str(e):
wrap_bare_types(tools)
else:
raise Prevention
- Never use shorthand bare type strings
- Wrap every property value in {"type": ...}
When it happens
Trigger: A properties entry like "city": "string" (bare type string) or a non-string key, when building the Kimi K3 structural tag.
Common situations: Shorthand schemas from tutorials ("type": "string" written as just "string"); tool definitions produced by LLMs that inline type names; serialization that turns schema dicts into strings.
Related errors
- Kimi K3 additional parameter schema accepts no values
- Kimi K3 tool parameters 'properties' must be an object
- Kimi K3 strict tool {tool.function.name!r} must define param
- Kimi K3 tool parameters 'required' must be a string list
- Kimi K3 required parameters are missing schemas: {sorted(mis
AI-assisted analysis of sgl-project/sglang@0132848349 (2026-08-28).
Data as JSON: /api/errors/21d9d69e2aa8ad2c.
Report an issue: GitHub.