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

  1. Remove return values from @event handlers — use bare 'return' for early exits
  2. If the caller needs a response, switch to @rpc with the response type annotated
  3. 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

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


AI-assisted analysis of microsoft/autogen@027ecf0a37 (2026-08-15). Data as JSON: /api/errors/1225065eca33bf66. Report an issue: GitHub.