zylon-ai/private-gpt · error · ValueError
Expected list or dict with 'items' key, got {type(obj)}
Error message
Expected list or dict with 'items' key, got {type(obj)} What it means
Raised by the custom model_validate on the dynamic ArrayModel generated from array JSON schemas (create_model_from_json_schema for type=array). The override accepts either a bare Python list (wrapped as items) or a dict containing an "items" key; anything else — a string, number, None, or an items-less dict — raises ValueError with the offending type name.
Source
Thrown at private_gpt/chat/schema_models.py:353
strict: bool | None = None,
extra: ExtraValues | None = None,
from_attributes: bool | None = None,
context: Any | None = None,
by_alias: bool | None = None,
by_name: bool | None = None,
) -> Self:
"""Accept array data directly."""
if isinstance(obj, list):
return cls(items=obj)
elif isinstance(obj, dict) and "items" in obj:
return super().model_validate(
obj,
strict=strict,
from_attributes=from_attributes,
context=context,
)
else:
raise ValueError(
f"Expected list or dict with 'items' key, got {type(obj)}"
)
@classmethod
def model_json_schema(
cls,
by_alias: bool = True,
ref_template: str = DEFAULT_REF_TEMPLATE,
schema_generator: type[GenerateJsonSchema] = GenerateJsonSchema,
mode: JsonSchemaMode = "validation",
*,
union_format: Literal["any_of", "primitive_type_array"] = "any_of",
) -> dict[str, Any]:
"""Return the original array schema, not wrapped in object schema."""
return schema
model_config = ConfigDict(populate_by_name=True, use_attribute_docstrings=True)
View on GitHub (pinned to 4a030776a3)
Solutions
- Parse JSON text first, then validate: ArrayModel.model_validate(json.loads(raw)).
- Pass a bare list directly: ArrayModel.model_validate([1, 2, 3]) — the override wraps it.
- If using the dict form, keep the 'items' key exactly (or the configured alias) — model_dump_json round-trips with it.
- Check the reported type in the message ({type(obj)}) to identify what actually arrived.
Example fix
// before model = ArrayModel.model_validate(raw_llm_output) # raw is a str // after import json model = ArrayModel.model_validate(json.loads(raw_llm_output))
Defensive patterns
Strategy: try-catch
Validate before calling
import json
if isinstance(data, (str, bytes)):
data = json.loads(data)
if isinstance(data, dict) and "items" not in data and "values" not in data:
data = list(data.values())[0] if len(data) == 1 else data Type guard
def is_array_model_input(obj: object) -> bool:
return isinstance(obj, list) or (isinstance(obj, dict) and "items" in obj) Try / catch
try:
model = ArrayModel.model_validate(payload)
except ValueError:
parsed = json.loads(payload) if isinstance(payload, str) else payload
model = ArrayModel.model_validate(parsed) Prevention
- json.loads LLM JSON output before model_validate.
- Round-trip with model_dump_json/model_validate pairs from the same generated model.
- Check the reported type in the message to identify the mismatch.
When it happens
Trigger: Calling ArrayModel.model_validate(json_string) where json_string is a str like '[1,2]'; model_validate({"values": [...]}) (dict without 'items'); model_validate(None) or model_validate(42). Happens when structured chat output is parsed into the dynamically generated array model.
Common situations: Feeding raw LLM JSON text responses into model_validate without json.loads; renaming the wrapper key in serialized output (dumping by items alias off); validating objects produced by a different schema.
Related errors
- Schema must define a 'type' field
- Array schemas must define 'items'
- Array 'items' must be a dictionary representing JSON Schema
- Object schemas must define 'properties'
- 'oneOf' must be an array of schemas
AI-assisted analysis of zylon-ai/private-gpt@4a030776a3 (2026-08-15).
Data as JSON: /api/errors/de0013e1bce216ae.
Report an issue: GitHub.