zylon-ai/private-gpt · error · TypeError
REQUEST_TOO_LARGE_ERROR
REQUEST_TOO_LARGE_ERROR
Error message
structured_outputs JSON must decode to an object; got {type(structured_outputs).__name__} What it means
TypeError raised when the structured_outputs string parsed as valid JSON but decoded to a non-object top-level value (list, string, number, bool, null). The normalizer requires a JSON object because it must map keys like json/json_schema into StructuredOutputsParams fields; arrays or scalars are meaningless there.
Source
Thrown at private_gpt/components/llm/custom/base.py:127
API serializers use ``json`` instead of the model's internal
``json_schema`` field. Normalize those representations before backend
specific code accesses the typed fields.
"""
if structured_outputs is None:
return None
if isinstance(structured_outputs, StructuredOutputsParams):
return structured_outputs
if isinstance(structured_outputs, str):
try:
structured_outputs = json.loads(structured_outputs)
except json.JSONDecodeError as exc:
raise ValueError(
"structured_outputs must be a StructuredOutputsParams, "
"mapping, JSON object string, or None"
) from exc
if not isinstance(structured_outputs, Mapping):
raise TypeError(
"structured_outputs JSON must decode to an object; "
f"got {type(structured_outputs).__name__}"
)
if isinstance(structured_outputs, Mapping):
values = dict(structured_outputs)
if "json" in values and "json_schema" not in values:
values["json_schema"] = values.pop("json")
return StructuredOutputsParams.model_validate(values)
raise TypeError(
"structured_outputs must be a StructuredOutputsParams, mapping, "
"JSON object string, or None; "
f"got {type(structured_outputs).__name__}"
)
class SamplingParameters(BaseModel):View on GitHub (pinned to 4a030776a3)
Solutions
- Wrap the schema in an object: use {"json_schema": {...}} not a bare array.
- If the string decodes to another string, decode again or stop pre-encoding the payload.
- Read the type name in the message (got list / got str) to see exactly what the decode produced.
- Pass a StructuredOutputsParams or plain dict to bypass string handling entirely.
Example fix
# before
params = '[{"name": "answer", "type": "object"}]'
# after
params = {"json_schema": {"name": "answer", "type": "object", "schema": {...}}} Defensive patterns
Strategy: type-guard
Validate before calling
import json
obj = json.loads(structured_outputs) if isinstance(structured_outputs, str) else structured_outputs
if not isinstance(obj, dict):
raise TypeError(f'structured_outputs root must be an object, got {type(obj).__name__}') Type guard
from collections.abc import Mapping
def is_structured_outputs_mapping(value: object) -> bool:
if isinstance(value, str):
try:
value = json.loads(value)
except json.JSONDecodeError:
return False
return isinstance(value, Mapping) Try / catch
try:
llm.stream_chat(messages, structured_outputs=payload)
except TypeError as e:
if 'must decode to an object' in str(e):
payload = {'json_schema': payload[0]} # unwrap array-wrapped schema Prevention
- Always wrap schemas in {"json_schema": ...} objects, never bare arrays.
- Watch out for double-encoded JSON — decode until the root is a dict.
When it happens
Trigger: Passing structured_outputs='[{"json_schema": ...}]' (array-wrapped schema) or '"{""json_schema"": ...}"' (still a string after decode) — anything whose decoded root is not a Mapping.
Common situations: Schemas authored as JSON arrays of definitions; double-encoded JSON strings that decode to a str; copying schema fragments from OpenAPI files that root in lists.
Related errors
- INVALID_REQUEST_ERROR
- Last item is a FlexibleModel, expected a specific output_cls
- No items returned from astream_structured_predict
- No items returned from astream_structured_chat
- Invalid reasoning_effort budget: {budget}. Must be a number
AI-assisted analysis of zylon-ai/private-gpt@4a030776a3 (2026-08-15).
Data as JSON: /api/errors/691d1fb2e3aa9cf8.
Report an issue: GitHub.