sgl-project/sglang · error · ValueError

Kimi K3 tool parameters 'required' must be a string list

Error message

Kimi K3 tool parameters 'required' must be a string list

What it means

In strict mode the Kimi K3 structural-tag builder reads tool.parameters.required and requires it to be a list of strings. Any other shape (string, dict, list containing non-strings) prevents computing the required-property set, so it fails fast.

Source

Thrown at python/sglang/srt/function_call/kimik3_structural_tag.py:387

    if not variants:
        raise ValueError("Kimi K3 additional parameter schema accepts no values")
    content = variants[0] if len(variants) == 1 else OrFormat(elements=variants)
    return TagFormat(
        begin='<|open|>argument key="',
        content=content,
        end=ARGUMENT_CLOSE,
    )


def _strict_arguments_format(parameters: Dict[str, Any]) -> Format:
    properties = parameters.get("properties", {})
    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"
                )

View on GitHub (pinned to 0132848349)

Solutions

  1. Make required a list of property-name strings, e.g. ["city", "units"]
  2. Omit required entirely if no property is mandatory
  3. Validate with a JSON Schema linter/meta-schema before launching the server

Example fix

// before
"required": "city"
// after
"required": ["city"]
Defensive patterns

Strategy: validation

Validate before calling

req = params.get("required", [])
assert isinstance(req, list) and all(isinstance(x, str) for x in req)

Type guard

def valid_required(params: dict) -> bool:
    r = params.get("required", [])
    return isinstance(r, list) and all(isinstance(i, str) for i in r)

Try / catch

try:
    build_tag(tools)
except ValueError as e:
    if "required" in str(e):
        normalize_required(tools)
    else:
        raise

Prevention

When it happens

Trigger: A tool schema with "required": "city", "required": {"city": true}, or "required": ["city", 3].

Common situations: Schemas written from memory where required is given as a single name or an object map; loose conversions from Pydantic or OpenAPI that emit non-standard required shapes.

Related errors


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