sgl-project/sglang · error · ValueError

Kimi K3 tool parameters 'properties' must be an object

Error message

Kimi K3 tool parameters 'properties' must be an object

What it means

The Kimi K3 strict arguments builder requires tool.parameters.properties to be a JSON object (dict) so it can emit a per-property argument format. A non-dict value (string, list, null-like) makes it impossible to enumerate properties, so it raises.

Source

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

        )
        for json_type, value_format in _argument_value_variants(
            schema, root_schema, loose_strings=loose_strings
        )
    ]
    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)

View on GitHub (pinned to 0132848349)

Solutions

  1. Fix the tool definition so properties is an object: {"name": {schema}, ...}
  2. Validate tool schemas with a JSON Schema draft validator against a proper JSON-Schema meta-schema before sending them
  3. If converting from another format, map list-style params into an object

Example fix

// before
"parameters": {"type": "object", "properties": [{"name": "city", "type": "string"}]}
// after
"parameters": {"type": "object", "properties": {"city": {"type": "string"}}}
Defensive patterns

Strategy: validation

Validate before calling

assert isinstance(tool["parameters"].get("properties", {}), dict), "properties must be an object"

Type guard

def valid_properties(params: dict) -> bool:
    p = params.get("properties", {})
    return isinstance(p, dict)

Try / catch

try:
    resp = client.chat(..., tools=tools)
except ValueError as e:
    if "properties" in str(e):
        fix_properties_shape(tools); retry_once = True
    else:
        raise

Prevention

When it happens

Trigger: A tool whose parameters dict has "properties": [...] or "properties": "foo" instead of an object mapping names to schemas.

Common situations: Schemas authored by hand or converted from OpenAPI/other formats that mangle properties into a list of {name, type} entries; LLM-generated tool definitions.

Related errors


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