microsoft/semantic-kernel · error · ServiceInvalidExecutionSettingsError
response_format must be a dictionary, a subclass of BaseMode
Error message
response_format must be a dictionary, a subclass of BaseModel, a Python class/type, or None
What it means
The response_format field on OpenAIChatPromptExecutionSettings only accepts one of: a dict, a pydantic BaseModel subclass, a plain Python class/type, or None. If none of these isinstance/issubclass checks match (e.g. passing an instance object, a list, a string, or an integer), the validator falls through to the else branch and raises ServiceInvalidExecutionSettingsError.
Source
Thrown at python/semantic_kernel/connectors/ai/open_ai/prompt_execution_settings/open_ai_prompt_execution_settings.py:143
if isinstance(response_format, dict):
if response_format.get("type") == "json_object":
return values
if response_format.get("type") == "json_schema":
json_schema = response_format.get("json_schema")
if isinstance(json_schema, dict):
values["structured_json_response"] = True
return values
raise ServiceInvalidExecutionSettingsError(
"If response_format has type 'json_schema', 'json_schema' must be a valid dictionary."
)
if isinstance(response_format, type):
if issubclass(response_format, BaseModel):
values["structured_json_response"] = True
else:
values["structured_json_response"] = True
else:
raise ServiceInvalidExecutionSettingsError(
"response_format must be a dictionary, a subclass of BaseModel, a Python class/type, or None"
)
return values
class OpenAIEmbeddingPromptExecutionSettings(PromptExecutionSettings):
"""Specific settings for the text embedding endpoint."""
input: str | list[str] | list[int] | list[list[int]] | None = None
ai_model_id: Annotated[str | None, Field(serialization_alias="model")] = None
encoding_format: Literal["float", "base64"] | None = None
user: str | None = None
extra_headers: dict | None = None
extra_query: dict | None = None
extra_body: dict | None = None
timeout: float | None = None
dimensions: Annotated[int | None, Field(gt=0, le=3072)] = NoneView on GitHub (pinned to c028a0c7dc)
Solutions
- Pass the BaseModel subclass (the type), not an instance: response_format=MyModel, not MyModel().
- If passing a string, parse it first: response_format=json.loads(my_string) so it becomes a dict.
- Set response_format to None to disable structured output entirely.
Example fix
// before settings.response_format = MyModel() # instance — fails // after settings.response_format = MyModel # class/type — works
Defensive patterns
Strategy: type-guard
Validate before calling
from pydantic import BaseModel
def validate_response_format(response_format) -> None:
if response_format is None:
return
if isinstance(response_format, dict):
return
if isinstance(response_format, type) and issubclass(response_format, BaseModel):
return
if isinstance(response_format, type):
return
raise TypeError(
'response_format must be a dict, a BaseModel subclass, a Python type, or None; '
f'got {type(response_format).__name__}'
) Type guard
from pydantic import BaseModel
def is_valid_response_format(rf) -> bool:
if rf is None:
return True
if isinstance(rf, dict):
return True
if isinstance(rf, type) and (issubclass(rf, BaseModel) or True):
return True
return False Try / catch
from semantic_kernel.exceptions import ServiceInvalidExecutionSettingsError
try:
settings = OpenAIChatPromptExecutionSettings(response_format=rf)
except ServiceInvalidExecutionSettingsError as e:
if 'must be a dictionary' in str(e):
rf = type(rf) if isinstance(rf, BaseModel) else rf # pass class not instance
settings = OpenAIChatPromptExecutionSettings(response_format=rf) Prevention
- Pass the BaseModel class (type), never an instance, as response_format.
- If deserializing from JSON, parse strings with json.loads before assignment.
- Default response_format to None rather than guessing a format.
When it happens
Trigger: Passing an already-instantiated BaseModel object (not the class) as response_format; passing a list, tuple, string, or number; passing a JSON string instead of a parsed dict.
Common situations: Confusing the class and instance: response_format=MyModel() instead of response_format=MyModel; passing a JSON-encoded string from an API payload without json.loads(); passing a frozenset or other non-type non-dict object.
Related errors
- When used with number_of_responses, best_of controls the num
- If response_format has type 'json_schema', 'json_schema' mus
- Invalid image size: {size.width}x{size.height}.
- OPENAI_API_KEY is not set.
- OPENAI_API_KEY is not set.
AI-assisted analysis of microsoft/semantic-kernel@c028a0c7dc (2026-08-13).
Data as JSON: /api/errors/958510311f1261ac.
Report an issue: GitHub.