zylon-ai/private-gpt · error · ValueError

Object schemas must define 'properties'

Error message

Object schemas must define 'properties'

What it means

Raised by the top-level _validate_json_schema when the root schema declares "type": "object" but contains no "properties" key. The dynamic-model builder needs at least a properties map (even empty) to construct fields for the Pydantic model. Only the root object schema requires properties; nested object property schemas are validated non-strictly and may omit them.

Source

Thrown at private_gpt/chat/schema_models.py:151

    """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)
            return

    if "type" not in schema:
        raise ValueError("Schema must define a 'type' field")

    if schema["type"] == "object":
        if "properties" not in schema:
            raise ValueError("Object schemas must define 'properties'")
        for _, prop_schema in schema.get("properties", {}).items():
            _validate_json_schema_item(prop_schema, strict=False)
    elif schema["type"] == "array":
        _validate_json_schema_item(schema.get("items", {}))
    else:
        pass


def _resolve_field_name_collisions(field_name: str, used_names: set[str]) -> str:
    """Resolve field name collisions by appending counter."""
    if field_name not in used_names:
        return field_name

    counter = 1
    while f"{field_name}_{counter}" in used_names:
        counter += 1

    return f"{field_name}_{counter}"

View on GitHub (pinned to 4a030776a3)

Solutions

  1. Add "properties": {} (or the real field definitions) to the root object schema.
  2. If the model should capture arbitrary keys, still declare "properties" and document that only listed fields become model fields.
  3. Validate with this helper (or jsonschema) client-side before calling the chat API.

Example fix

// before
{"type": "object"}

// after
{"type": "object", "properties": {"city": {"type": "string"}}}
Defensive patterns

Strategy: validation

Validate before calling

if schema.get("type") == "object" and "properties" not in schema:
    schema.setdefault("properties", {})

Type guard

def object_schema_has_properties(s: dict) -> bool:
    return s.get("type") != "object" or "properties" in s

Try / catch

try:
    create_model_from_json_schema(schema)
except ValueError as e:
    if "properties" in str(e):
        schema.setdefault("properties", {})
        model = create_model_from_json_schema(schema)
    else:
        raise

Prevention

When it happens

Trigger: Passing {"type": "object"} alone, or {"type": "object", "additionalProperties": {...}} without a "properties" key, as the root schema to create_model_from_json_schema.

Common situations: Map/dict-style output schemas where the author expects additionalProperties to define values; minimal placeholder schemas; schemas stripped during serialization (exclude_none dropping an empty properties dict).

Related errors


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