zylon-ai/private-gpt · error · ValueError
Array 'items' must be a dictionary representing JSON Schema
Error message
Array 'items' must be a dictionary representing JSON Schema
What it means
Raised by _validate_json_schema_item when an array schema's "items" value is not a dict. JSON Schema requires items to be a schema object; this validator enforces dict form because it recursively builds Pydantic models from it. Tuples, lists (per-item form), or strings like "string" all trigger it.
Source
Thrown at private_gpt/chat/schema_models.py:125
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"):
if composition_key in schema:
for sub_schema in schema[composition_key]:
_validate_json_schema_item(sub_schema, strict=False)View on GitHub (pinned to 4a030776a3)
Solutions
- Wrap the item type in a schema object: {"items": {"type": "string"}} instead of {"items": "string"}.
- Replace tuple-form items arrays with {"items": {"anyOf": [ ... ]}}.
- If items comes from user input, coerce/validate it to a dict before calling the API.
Example fix
// before
{"type": "array", "items": "string"}
// after
{"type": "array", "items": {"type": "string"}} Defensive patterns
Strategy: validation
Validate before calling
def coerce_items(node: dict) -> None:
if node.get("type") == "array":
items = node.get("items")
if isinstance(items, str):
node["items"] = {"type": items}
elif isinstance(items, list):
node["items"] = {"anyOf": items}
if not isinstance(node.get("items"), dict):
raise ValueError(f"Bad items for array: {items!r}") Type guard
def has_dict_items(s: dict) -> bool:
return s.get("type") != "array" or isinstance(s.get("items"), dict) Try / catch
try:
create_model_from_json_schema(schema)
except ValueError as e:
raise HTTPException(400, detail=str(e)) from e Prevention
- Always wrap item types as objects: {"items": {"type": ...}}.
- Avoid the legacy tuple-form items array.
- Validate schema shape with a unit test before integrating user input.
When it happens
Trigger: Passing {"type": "array", "items": "string"} (type as a bare string), {"items": [ {"type": "string"}, {"type": "number"} ]} (tuple-validation array form), or items set to None within a schema sent to create_model_from_json_schema.
Common situations: Translating from Python type hints or OpenAPI specs where item types are strings; using the legacy JSON Schema array-form items; YAML configs where items collapses to a scalar.
Related errors
- Schema must define a 'type' field
- Array schemas must define 'items'
- Object schemas must define 'properties'
- Expected list or dict with 'items' key, got {type(obj)}
- 'oneOf' must be an array of schemas
AI-assisted analysis of zylon-ai/private-gpt@4a030776a3 (2026-08-15).
Data as JSON: /api/errors/50a731817b5ed36a.
Report an issue: GitHub.