microsoft/autogen · error · ValueError

json_output must be a boolean, a BaseModel subclass or None.

Error message

json_output must be a boolean, a BaseModel subclass or None.

What it means

In create(), json_output is validated to be exactly True/False, None, or a BaseModel subclass. Anything else (an int, a string, a BaseModel *instance* instead of the class, a dataclass) hits the elif chain's final raise. Note the message text omits the instance case, but passing an instance is the most common way to land here because isinstance(json_output, type) is False for instances.

Source

Thrown at python/packages/autogen-ext/src/autogen_ext/models/llama_cpp/_llama_cpp_completion_client.py:305

            if isinstance(msg, SystemMessage):
                converted_messages.append({"role": "system", "content": msg.content})
            elif isinstance(msg, UserMessage) and isinstance(msg.content, str):
                converted_messages.append({"role": "user", "content": msg.content})
            elif isinstance(msg, AssistantMessage) and isinstance(msg.content, str):
                converted_messages.append({"role": "assistant", "content": msg.content})
            elif (
                isinstance(msg, SystemMessage) or isinstance(msg, UserMessage) or isinstance(msg, AssistantMessage)
            ) and isinstance(msg.content, list):
                raise ValueError("Multi-part messages such as those containing images are currently not supported.")
            else:
                raise ValueError(f"Unsupported message type: {type(msg)}")

        if isinstance(json_output, type) and issubclass(json_output, BaseModel):
            create_args["response_format"] = {"type": "json_object", "schema": json_output.model_json_schema()}
        elif json_output is True:
            create_args["response_format"] = {"type": "json_object"}
        elif json_output is not False and json_output is not None:
            raise ValueError("json_output must be a boolean, a BaseModel subclass or None.")

        # Handle tool_choice parameter
        if tool_choice != "auto":
            warnings.warn(
                "tool_choice parameter is specified but LlamaCppChatCompletionClient does not support it. "
                "This parameter will be ignored.",
                UserWarning,
                stacklevel=2,
            )

        if self.model_info["function_calling"]:
            # Run this in on the event loop to avoid blocking.
            response_future = asyncio.get_event_loop().run_in_executor(
                None,
                lambda: self.llm.create_chat_completion(
                    messages=converted_messages, tools=convert_tools(tools), stream=False, **create_args
                ),
            )

View on GitHub (pinned to 027ecf0a37)

Solutions

  1. Pass the class, not an instance: json_output=MyModel (no parentheses)
  2. Pass json_output=True for plain JSON mode, False or None to disable
  3. If json_output comes from config, coerce it first: json_output = {'true': True, 'false': False}.get(str(cfg).lower(), cfg)

Example fix

# before
result = await client.create(messages, json_output=StepPlan())  # instance -> ValueError

# after
result = await client.create(messages, json_output=StepPlan)  # the class itself
Defensive patterns

Strategy: type-guard

Validate before calling

from pydantic import BaseModel

def coerce_json_output(v: object) -> bool | type[BaseModel] | None:
    if v is None or isinstance(v, bool):
        return v
    if isinstance(v, type) and issubclass(v, BaseModel):
        return v
    if isinstance(v, str) and v.lower() in ("true", "false"):
        return v.lower() == "true"
    raise TypeError(f"json_output cannot be {type(v)!r}")

result = await client.create(messages, json_output=coerce_json_output(cfg["json_output"]))

Type guard

def is_valid_json_output(v: object) -> TypeGuard[bool | type[BaseModel] | None]:
    return v is None or isinstance(v, bool) or (isinstance(v, type) and issubclass(v, BaseModel))

Try / catch

try:
    result = await client.create(messages, json_output=jo)
except ValueError as e:
    if "json_output must be" in str(e):
        result = await client.create(messages, json_output=bool(jo))
    else:
        raise

Prevention

When it happens

Trigger: create(messages, json_output=MyModel()) — instance instead of class; json_output=1 or json_output='json'; passing a pydantic dataclass or TypedDict class; forwarding an unvalidated config value into json_output.

Common situations: Dynamically deserializing config (YAML/JSON) where json_output arrives as the string 'true'; passing a schema instance built elsewhere; copy-paste from code that used a different client whose API takes an instance.

Related errors


AI-assisted analysis of microsoft/autogen@027ecf0a37 (2026-08-15). Data as JSON: /api/errors/d9cbae7f007031fd. Report an issue: GitHub.