{"record":{"id":"1e9fba659f57e24c","repo":"microsoft/autogen","slug":"return-type-type-return-value-not-in-return-typ","errorCode":null,"errorMessage":"Return type {type(return_value)} not in return types {return_types}","messagePattern":"Return type (.+?) not in return types (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/packages/autogen-core/src/autogen_core/_routed_agent.py","lineNumber":153,"sourceCode":"\n        if return_types is None:\n            raise AssertionError(\"Return type not found\")\n\n        # Convert target_types to list and stash\n\n        @wraps(func)\n        async def wrapper(self: AgentT, message: ReceivesT, ctx: MessageContext) -> ProducesT:\n            if type(message) not in target_types:\n                if strict:\n                    raise CantHandleException(f\"Message type {type(message)} not in target types {target_types}\")\n                else:\n                    logger.warning(f\"Message type {type(message)} not in target types {target_types}\")\n\n            return_value = await func(self, message, ctx)\n\n            if AnyType not in return_types and type(return_value) not in return_types:\n                if strict:\n                    raise ValueError(f\"Return type {type(return_value)} not in return types {return_types}\")\n                else:\n                    logger.warning(f\"Return type {type(return_value)} not in return types {return_types}\")\n\n            return return_value\n\n        wrapper_handler = cast(MessageHandler[AgentT, ReceivesT, ProducesT], wrapper)\n        wrapper_handler.target_types = list(target_types)\n        wrapper_handler.produces_types = list(return_types)\n        wrapper_handler.is_message_handler = True\n        wrapper_handler.router = match or (lambda _message, _ctx: True)\n\n        return wrapper_handler\n\n    if func is None and not callable(func):\n        return decorator\n    elif callable(func):\n        return decorator(func)\n    else:","sourceCodeStart":135,"sourceCodeEnd":171,"githubUrl":"https://github.com/microsoft/autogen/blob/027ecf0a379bcc1d09956d46d12d44a3ad9cee14/python/packages/autogen-core/src/autogen_core/_routed_agent.py#L135-L171","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"# before\n@rpc\nasync def handle(self, message: Ask, ctx: MessageContext) -> Answer:\n    if not ask.valid:\n        return  # None -> ValueError\n\n# after\n@rpc\nasync def handle(self, message: Ask, ctx: MessageContext) -> Answer:\n    if not ask.valid:\n        return Answer(error=\"invalid\")","handlingStrategy":"try-catch","validationCode":"def returns_match(handler_wrapper, value) -> bool:\n    from typing import Any\n    return Any in handler_wrapper.produces_types or type(value) in handler_wrapper.produces_types","typeGuard":"def return_value_ok(produces_types, value) -> bool:\n    return type(value) in produces_types","tryCatchPattern":"try:\n    result = await agent.on_message(msg, ctx)\nexcept ValueError as e:\n    if \"Return type\" in str(e):\n        logger.error(\"handler %s returned wrong type: %s\", handler, e)\n    raise","preventionTips":["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"],"tags":["python","message-routing","runtime","type-mismatch","autogen-core"],"backgroundTag":null,"analyzedSha":"027ecf0a379bcc1d09956d46d12d44a3ad9cee14","analyzedAt":"2026-08-15T03:38:00.719Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}