zylon-ai/private-gpt · error · ValueError

INVALID_REQUEST_ERROR

INVALID_REQUEST_ERROR

Error message

structured_outputs must be a StructuredOutputsParams, mapping, JSON object string, or None

What it means

ValueError raised while normalizing a structured_outputs parameter: the value was a string, but json.loads failed to parse it as JSON. The normalizer accepts StructuredOutputsParams, mappings, JSON-object strings, or None — a malformed JSON string fails at the json.loads step with this message, chained from JSONDecodeError.

Source

Thrown at private_gpt/components/llm/custom/base.py:122

    structured_outputs: (StructuredOutputsParams | Mapping[str, Any] | str | None),
) -> StructuredOutputsParams | None:
    """Normalize structured-output values crossing untyped boundaries.

    Chat parameters can be restored from serialized checkpoint data, and some
    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; "

View on GitHub (pinned to 4a030776a3)

Solutions

  1. Build the JSON string with json.dumps(schema_dict) instead of hand-writing it.
  2. Paste the string into a JSON validator (or json.loads in a REPL) to find the syntax error position from the chained JSONDecodeError.
  3. Prefer passing the schema as a dict/StructuredOutputsParams object rather than a string.
  4. Check for double-encoded JSON (a string containing an escaped JSON string) and decode once.

Example fix

# before
llm.chat(messages, structured_outputs='{"json_schema": ' + schema_str)  # broken拼接

# after
import json
llm.chat(messages, structured_outputs=json.dumps({"json_schema": schema_dict}))
Defensive patterns

Strategy: validation

Validate before calling

import json
if isinstance(structured_outputs, str):
    try:
        json.loads(structured_outputs)
    except json.JSONDecodeError as e:
        raise ValueError(f'invalid structured_outputs JSON at pos {e.pos}: {e.msg}') from e

Type guard

def is_valid_structured_outputs_str(value: str) -> bool:
    try:
        obj = json.loads(value)
    except json.JSONDecodeError:
        return False
    return isinstance(obj, dict)

Try / catch

try:
    llm.stream_chat(messages, structured_outputs=schema_str)
except ValueError as e:
    if 'structured_outputs must be' in str(e):
        schema_str = json.dumps(schema_dict)  # rebuild safely and retry

Prevention

When it happens

Trigger: Passing structured_outputs as a string like "{json_schema: ...}" (missing quotes / trailing commas / truncated payload) to an LLM call that normalizes the parameter via this function. Any syntactically invalid JSON string triggers it.

Common situations: Schema strings built by manual f-string concatenation instead of json.dumps; user-supplied schema from a request body pasted with smart quotes or newlines; truncated payloads from proxies; double-encoded JSON.

Related errors


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