zylon-ai/private-gpt · error · ValueError

Array schemas must define 'items'

Error message

Array schemas must define 'items'

What it means

Raised by _validate_json_schema_item when a schema declares "type": "array" but has no "items" key. The validator requires every array schema to describe its element schema, because create_model_from_json_schema must build a Pydantic model for the item type. It fires both at the top level and inside nested properties/items.

Source

Thrown at private_gpt/chat/schema_models.py:122

            _validate_json_schema_item(sub_schema, strict=False)
        return  # anyOf schemas don't need type field

    if "allOf" in schema:
        if not isinstance(schema["allOf"], list):
            raise ValueError("'allOf' must be an array of schemas")
        for sub_schema in schema["allOf"]:
            _validate_json_schema_item(sub_schema, strict=False)
        return  # allOf schemas don't need type field

    # Regular schema validation
    if "type" not in schema:
        if strict:
            raise ValueError("Schema must define a 'type' field")
        else:
            return  # Non-strict mode allows missing type

    if schema["type"] == "array" and "items" not in schema:
        raise ValueError("Array schemas must define 'items'")

    if schema["type"] == "array" and not isinstance(schema.get("items"), dict):
        raise ValueError("Array 'items' must be a dictionary representing JSON Schema")

    # Recursively validate array items
    if schema["type"] == "array":
        _validate_json_schema_item(schema.get("items", {}))


def _validate_json_schema(schema: dict[str, Any]) -> None:
    """Validate that the schema is a valid JSON Schema object."""
    if not isinstance(schema, dict):
        raise ValueError("Schema must be a dictionary representing JSON Schema")
    if not schema:
        return

    # Composition keywords at the top level are valid without a "type" field.
    for composition_key in ("allOf", "anyOf", "oneOf"):

View on GitHub (pinned to 4a030776a3)

Solutions

  1. Add an "items" schema to every "type": "array" node: {"type": "array", "items": {"type": "string"}}.
  2. For heterogeneous arrays use {"items": {"anyOf": [...]}} instead of omitting items.
  3. Run the schema through a JSON Schema linter (or this validator directly) before submitting the request.

Example fix

// before
{"type": "object", "properties": {"tags": {"type": "array"}}}

// after
{"type": "object", "properties": {"tags": {"type": "array", "items": {"type": "string"}}}}
Defensive patterns

Strategy: validation

Validate before calling

def ensure_array_items(node: dict) -> None:
    if node.get("type") == "array" and "items" not in node:
        node["items"] = {"type": "string"}  # or reject explicitly

def walk(schema: dict):
    ensure_array_items(schema)
    for key in ("properties",):
        for sub in schema.get(key, {}).values():
            walk(sub)
    if isinstance(schema.get("items"), dict):
        walk(schema["items"])

Type guard

def arrays_have_items(s: dict) -> bool:
    ok = s.get("type") != "array" or "items" in s
    return ok and all(arrays_have_items(v) for v in s.get("properties", {}).values()) and (not isinstance(s.get("items"), dict) or arrays_have_items(s["items"]))

Try / catch

try:
    create_model_from_json_schema(schema)
except ValueError as e:
    if "items" in str(e):
        raise HTTPException(400, "Every array schema must define 'items'") from e
    raise

Prevention

When it happens

Trigger: Passing a schema such as {"type": "array"} or {"type": "object", "properties": {"tags": {"type": "array"}}} to create_model_from_json_schema or any structured-output API that validates schemas with this helper.

Common situations: Hand-written or LLM-generated tool schemas that treat arrays as self-describing; porting TypeScript types (string[]) to JSON Schema and forgetting the items mapping; schemas trimmed for brevity before sending to the chat API.

Related errors


AI-assisted analysis of zylon-ai/private-gpt@4a030776a3 (2026-08-15). Data as JSON: /api/errors/2da24b698d9aed77. Report an issue: GitHub.