microsoft/semantic-kernel · error · ValueError

No serializers found for type {t}.

Error message

No serializers found for type {t}.

What it means

Raised when a RoutedAgent is registered. _handles_types() discovers each handler's target_types and calls try_get_known_serializers_for_type(t), which only knows three families: Pydantic BaseModel, dataclass, and protobuf Message subclasses. If a handler declares a target type outside those families, no serializer is found and ValueError is raised, blocking registration.

Source

Thrown at python/semantic_kernel/agents/runtime/core/routed_agent.py:524

            if callable(getattr(cls, attr, None)):
                # Since we are getting it from the class, self is not bound
                handler = getattr(cls, attr)
                if hasattr(handler, "is_message_handler"):
                    handlers.append(cast(MessageHandler[Any, Any, Any], handler))
        return handlers

    @classmethod
    def _handles_types(cls) -> list[tuple[type[Any], list[MessageSerializer[Any]]]]:
        # TODO(evmattso): handle deduplication
        handlers = cls._discover_handlers()
        types: list[tuple[type[Any], list[MessageSerializer[Any]]]] = []
        types.extend(cls.internal_extra_handles_types)
        for handler in handlers:
            for t in handler.target_types:
                # TODO(evmattso): support different serializers
                serializers = try_get_known_serializers_for_type(t)
                if len(serializers) == 0:
                    raise ValueError(f"No serializers found for type {t}.")

                types.append((t, try_get_known_serializers_for_type(t)))
        return types


# endregion

View on GitHub (pinned to c028a0c7dc)

Solutions

  1. Make the message type a Pydantic BaseModel, a dataclass, or a protobuf Message subclass.
  2. Or register a custom MessageSerializer and add it to the registry / the agent's internal_extra_handles_types.
  3. If using inheritance, ensure the concrete declared type is itself one of the three supported families.

Example fix

// before
class MyMessage:  # plain class -> no serializer
    ...

@rpc
async def handle(self, message: MyMessage, ctx: MessageContext) -> None: ...

// after
from pydantic import BaseModel

class MyMessage(BaseModel):
    ...

@rpc
async def handle(self, message: MyMessage, ctx: MessageContext) -> None: ...
Defensive patterns

Strategy: validation

Validate before calling

import dataclasses
from pydantic import BaseModel
from google.protobuf.message import Message
from semantic_kernel.agents.runtime.core.serialization import try_get_known_serializers_for_type

def has_serializer(t: type) -> bool:
    return len(try_get_known_serializers_for_type(t)) > 0

Type guard

def is_serializable_message(t: type) -> bool:
    return isinstance(t, type) and (
        issubclass(t, BaseModel) or dataclasses.is_dataclass(t) or issubclass(t, Message)
    )

Prevention

When it happens

Trigger: An @rpc/@event/@message_handler whose 'message' annotation is a plain class, TypedDict, namedtuple, Enum, primitive (int/str), or any non-{BaseModel, dataclass, protobuf} type, and the agent is then registered with the runtime (which triggers _handles_types).

Common situations: Using a TypedDict or a vanilla class as a message; using an Enum or a primitive; forgetting to make the message a dataclass/pydantic model; using a third-party non-serializable type.

Related errors


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