microsoft/autogen · error · ValueError
Return type {type(return_value)} not in return types {return
Error message
Return type {type(return_value)} not in return types {return_types} What it means
After the handler coroutine returns, the wrapper verifies the returned value's concrete type() against the declared return types (unless Any is among them). With strict=True a mismatch raises ValueError; with strict=False it logs a warning and still returns the value. This guards RPC contracts where the declared produces type determines response serialization.
Source
Thrown at python/packages/autogen-core/src/autogen_core/_routed_agent.py:153
if return_types is None:
raise AssertionError("Return type not found")
# Convert target_types to list and stash
@wraps(func)
async def wrapper(self: AgentT, message: ReceivesT, ctx: MessageContext) -> ProducesT:
if type(message) not in target_types:
if strict:
raise CantHandleException(f"Message type {type(message)} not in target types {target_types}")
else:
logger.warning(f"Message type {type(message)} not in target types {target_types}")
return_value = await func(self, message, ctx)
if AnyType not in return_types and type(return_value) not in return_types:
if strict:
raise ValueError(f"Return type {type(return_value)} not in return types {return_types}")
else:
logger.warning(f"Return type {type(return_value)} not in return types {return_types}")
return return_value
wrapper_handler = cast(MessageHandler[AgentT, ReceivesT, ProducesT], wrapper)
wrapper_handler.target_types = list(target_types)
wrapper_handler.produces_types = list(return_types)
wrapper_handler.is_message_handler = True
wrapper_handler.router = match or (lambda _message, _ctx: True)
return wrapper_handler
if func is None and not callable(func):
return decorator
elif callable(func):
return decorator(func)
else:View on GitHub (pinned to 027ecf0a37)
Solutions
- Return an instance of the exact annotated return type on every code path, including early returns
- Update the annotation to match what is actually returned (e.g. '-> Response | None' is not allowed for rpc; instead always return Response)
- If intentional, annotate the return as Any (the check is skipped when Any is in return_types) or pass strict=False to downgrade to a warning
Example fix
# before
@rpc
async def handle(self, message: Ask, ctx: MessageContext) -> Answer:
if not ask.valid:
return # None -> ValueError
# after
@rpc
async def handle(self, message: Ask, ctx: MessageContext) -> Answer:
if not ask.valid:
return Answer(error="invalid") Defensive patterns
Strategy: try-catch
Validate before calling
def returns_match(handler_wrapper, value) -> bool:
from typing import Any
return Any in handler_wrapper.produces_types or type(value) in handler_wrapper.produces_types Type guard
def return_value_ok(produces_types, value) -> bool:
return type(value) in produces_types Try / catch
try:
result = await agent.on_message(msg, ctx)
except ValueError as e:
if "Return type" in str(e):
logger.error("handler %s returned wrong type: %s", handler, e)
raise Prevention
- Audit every early-return path in handlers to ensure the annotated response type is returned
- Unit-test handlers directly and assert isinstance(result, AnnotatedResponse)
- Annotate '-> Any' only when the handler genuinely returns heterogeneous types
When it happens
Trigger: Handler annotated '-> Response' but returns None (no explicit return), returns a subclass/dict/dataclass instead of Response, or returns an object whose exact type() differs from every type in the declared return union.
Common situations: Forgetting a return statement on an early-exit path; refactoring the response model while keeping the old annotation; returning a pydantic model copy constructed via a different class (e.g. model_construct of a sibling); unit tests calling handlers directly and asserting on the ValueError.
Related errors
- Message type {type(message)} not in target types {target_typ
- Return type {type(return_value)} is not None.
- Agent with name {id.type} is not of type {type.__name__}. It
- Message must have a receiver to be sent.
- str(message.error)
AI-assisted analysis of microsoft/autogen@027ecf0a37 (2026-08-15).
Data as JSON: /api/errors/1e9fba659f57e24c.
Report an issue: GitHub.