microsoft/semantic-kernel · error · ValueError

Dataclass has a union type, which is not supported. To use a

Error message

Dataclass has a union type, which is not supported. To use a union, use a Pydantic model

What it means

Raised by DataclassJsonMessageSerializer.__init__ when the dataclass message contains a Union-typed field (contains_a_union returns True). The dataclass JSON serializer cannot represent unions, so construction is rejected and the library directs you to use a Pydantic model instead. Note: Optional[X] is itself a Union, so optional fields trigger this too.

Source

Thrown at python/semantic_kernel/agents/runtime/core/serialization.py:133

DataclassT = TypeVar("DataclassT", bound=IsDataclass)

JSON_DATA_CONTENT_TYPE = "application/json"
"""JSON data content type"""

# TODO(evmattso): what's the correct content type? There seems to be some disagreement over what it should be
PROTOBUF_DATA_CONTENT_TYPE = "application/x-protobuf"
"""Protobuf data content type"""


@experimental
class DataclassJsonMessageSerializer(MessageSerializer[DataclassT]):
    """Serializer for dataclass messages."""

    def __init__(self, cls: type[DataclassT]) -> None:
        """Initialize the serializer with a dataclass type."""
        if contains_a_union(cls):
            raise ValueError("Dataclass has a union type, which is not supported. To use a union, use a Pydantic model")

        if has_nested_dataclass(cls) or has_nested_base_model(cls):
            raise ValueError(
                "Dataclass has nested dataclasses or base models, which are not supported. To use nested types, "
                "use a Pydantic model"
            )

        self.cls = cls

    @property
    def data_content_type(self) -> str:
        """Return the data content type."""
        return JSON_DATA_CONTENT_TYPE

    @property
    def type_name(self) -> str:
        """Return the type name."""
        return _type_name(self.cls)

View on GitHub (pinned to c028a0c7dc)

Solutions

  1. Convert the message to a Pydantic BaseModel, which supports unions natively.
  2. Or eliminate the union by splitting into separate non-union dataclasses.
  3. Avoid Optional/Union fields on dataclass messages.

Example fix

// before
from dataclasses import dataclass
from typing import Optional

@dataclass
class Msg:
    value: Optional[int]  # Union -> ValueError

// after
from pydantic import BaseModel

class Msg(BaseModel):
    value: int | None
Defensive patterns

Strategy: validation

Validate before calling

from semantic_kernel.agents.runtime.core.serialization import contains_a_union
import dataclasses

def dataclass_ok(cls) -> bool:
    return dataclasses.is_dataclass(cls) and not contains_a_union(cls)

Type guard

def is_pydantic_or_flat_dataclass(cls) -> bool:
    from pydantic import BaseModel
    import dataclasses
    if isinstance(cls, type) and issubclass(cls, BaseModel):
        return True
    return dataclasses.is_dataclass(cls) and not contains_a_union(cls)

Prevention

When it happens

Trigger: Constructing/registering a dataclass message that has a field typed as Union[A, B], A | B, or Optional[A]; any field whose annotation resolves to a Union.

Common situations: Adding an optional or polymorphic field to a dataclass message; migrating a Pydantic model to a dataclass without removing unions.

Related errors


AI-assisted analysis of microsoft/semantic-kernel@c028a0c7dc (2026-08-13). Data as JSON: /api/errors/e670a5aac1f40c7a. Report an issue: GitHub.