microsoft/autogen · error · ValueError
Return type {type(return_value)} is not None.
Error message
Return type {type(return_value)} is not None. What it means
The @event wrapper enforces the 'events return nothing' contract: if the decorated coroutine returns a non-None value and strict=True, ValueError is raised; with strict=False the value is logged and discarded (the wrapper always returns None). This prevents silently losing data that the caller might expect back.
Source
Thrown at python/packages/autogen-core/src/autogen_core/_routed_agent.py:272
if return_types is None:
raise AssertionError("Return type not found. Please use `None` as the type hint of the return type.")
# Convert target_types to list and stash
@wraps(func)
async def wrapper(self: AgentT, message: ReceivesT, ctx: MessageContext) -> None:
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) # type: ignore
if return_value is not None:
if strict:
raise ValueError(f"Return type {type(return_value)} is not None.")
else:
logger.warning(f"Return type {type(return_value)} is not None. It will be ignored.")
return None
wrapper_handler = cast(MessageHandler[AgentT, ReceivesT, None], wrapper)
wrapper_handler.target_types = list(target_types)
wrapper_handler.produces_types = list(return_types)
wrapper_handler.is_message_handler = True
# Wrap the match function with a check on the is_rpc flag.
wrapper_handler.router = lambda _message, _ctx: (not _ctx.is_rpc) and (match(_message, _ctx) if match else True)
return wrapper_handler
if func is None and not callable(func):
return decorator
elif callable(func):
return decorator(func)View on GitHub (pinned to 027ecf0a37)
Solutions
- Remove return values from @event handlers — use bare 'return' for early exits
- If the caller needs a response, switch to @rpc with the response type annotated
- Set strict=False to downgrade to a warning while the value is still ignored
Example fix
# before
@event
async def on_event(self, message: Ev, ctx: MessageContext) -> None:
return compute(message) # ValueError when strict
# after
@event
async def on_event(self, message: Ev, ctx: MessageContext) -> None:
compute(message) Defensive patterns
Strategy: try-catch
Try / catch
try:
await agent.on_message(event, ctx)
except ValueError as e:
if "is not None" in str(e):
logger.error("@event handler returned a value: %s", e)
raise Prevention
- Never return values from @event handlers; use bare 'return' for early exits
- If a computed result is needed, publish it as a new event or move the handler to @rpc
When it happens
Trigger: An @event handler contains 'return something' or its last expression evaluates to a value; refactoring an @rpc handler into @event but leaving return statements; generator/expression-based bodies that accidentally return non-None.
Common situations: Reusing handler bodies between rpc and event variants; early 'return result' used as a short-circuit inside event handlers; tests asserting a return value from event handlers.
Related errors
- Message type {type(message)} not in target types {target_typ
- Return type {type(return_value)} not in return types {return
- Agent with name {id.type} is not of type {type.__name__}. It
- Invalid topic type: {self.type}. Must match the pattern: ^[\
- TopicId does not match the subscription
AI-assisted analysis of microsoft/autogen@027ecf0a37 (2026-08-15).
Data as JSON: /api/errors/1225065eca33bf66.
Report an issue: GitHub.