{"record":{"id":"9bb241e5d3a5e202","repo":"microsoft/semantic-kernel","slug":"return-type-type-return-value-is-not-none","errorCode":null,"errorMessage":"Return type {type(return_value)} is not None.","messagePattern":"Return type (.+?) is not None\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/semantic_kernel/agents/runtime/core/routed_agent.py","lineNumber":291,"sourceCode":"        return_types = get_types(type_hints[\"return\"])\n\n        if return_types is None:\n            raise AssertionError(\"Return type not found. Please use `None` as the type hint of the return type.\")\n\n        # Convert target_types to list and stash\n\n        @wraps(func)\n        async def wrapper(self: AgentT, message: ReceivesT, ctx: MessageContext) -> None:\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                logger.warning(f\"Message type {type(message)} not in target types {target_types}\")\n\n            return_value = await func(self, message, ctx)  # type: ignore\n\n            if return_value is not None:\n                if strict:\n                    raise ValueError(f\"Return type {type(return_value)} is not None.\")\n                logger.warning(f\"Return type {type(return_value)} is not None. It will be ignored.\")\n\n            return\n\n        wrapper_handler = cast(MessageHandler[AgentT, ReceivesT, None], 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        # Wrap the match function with a check on the is_rpc flag.\n        wrapper_handler.router = lambda _message, _ctx: (not _ctx.is_rpc) and (match(_message, _ctx) if match else True)\n\n        return wrapper_handler\n\n    if func is None and not callable(func):\n        return decorator\n    if callable(func):\n        return decorator(func)\n    raise ValueError(\"Invalid arguments\")","sourceCodeStart":273,"sourceCodeEnd":309,"githubUrl":"https://github.com/microsoft/semantic-kernel/blob/c028a0c7dc4f0814cdcbaba9d998f187a41197bf/python/semantic_kernel/agents/runtime/core/routed_agent.py#L273-L309","documentation":"Raised at runtime by the @event wrapper. Event handlers must return None (events are fire-and-forget). The wrapper awaits the function and, if the return value is not None, raises ValueError in strict mode (default True) or logs a warning otherwise. This enforces the event contract that events cannot produce responses.","triggerScenarios":"An @event handler returns a non-None value: an explicit return of a computed result/message, or an implicit return of an expression. Strict mode (default) turns it into a ValueError.","commonSituations":"Forgetting to drop a return statement after refactoring an RPC handler into an event handler; returning a status/ack object; an accidental trailing expression.","solutions":["Ensure the event handler returns nothing (end without return, or use a bare 'return' / 'return None').","If a value must come back, switch to @rpc.","Pass strict=False to downgrade to a warning if a stray return is acceptable."],"exampleFix":"// before\n@event\nasync def on_event(self, message: E, ctx: MessageContext) -> None:\n    return self.compute(message)  # non-None -> ValueError\n\n// after\n@event\nasync def on_event(self, message: E, ctx: MessageContext) -> None:\n    self.compute(message)","handlingStrategy":"validation","validationCode":"import asyncio\n\ndef returns_none_when_awaited(handler, *args) -> bool:\n    return asyncio.get_event_loop().run_until_complete(handler(*args)) is None","typeGuard":null,"tryCatchPattern":"try:\n    await runtime.send_message(msg, agent_id)\nexcept ValueError as e:\n    if 'is not None' in str(e):\n        logger.error('Event handler returned a value: %s', e)","preventionTips":["Event handlers must return None; add a test asserting the awaited result is None.","When converting an RPC handler to an event handler, strip every return statement.","Keep strict=True in CI to catch stray returns early."],"tags":["event-handler","return-value","runtime","contract"],"backgroundTag":null,"analyzedSha":"c028a0c7dc4f0814cdcbaba9d998f187a41197bf","analyzedAt":"2026-08-13T13:48:05.040Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}