microsoft/semantic-kernel · error · AssertionError
return not found in function signature
Error message
return not found in function signature
What it means
Raised by the @message_handler decorator when the decorated method has no return type annotation. The decorator inspects type_hints['return'] to determine which message types the handler produces, so a missing return annotation (even -> None) prevents routing of responses.
Source
Thrown at python/semantic_kernel/agents/runtime/core/routed_agent.py:135
func: The function to be decorated.
strict: If `True`, the handler will raise an exception if the message type or return type is not in the target
types. If `False`, it will log a warning instead.
match: A function that takes the message and the context as arguments and returns a boolean. This is used for
secondary routing after the message type. For handlers addressing the same message type, the match function
is applied in alphabetical order of the handlers and the first matching handler will be called while the
rest are skipped. If `None`, the first handler in alphabetical order matching the same message type will
be called.
"""
def decorator(
func: Callable[[AgentT, ReceivesT, MessageContext], Coroutine[Any, Any, ProducesT]],
) -> MessageHandler[AgentT, ReceivesT, ProducesT]:
type_hints = get_type_hints(func)
if "message" not in type_hints:
raise AssertionError("message parameter not found in function signature")
if "return" not in type_hints:
raise AssertionError("return not found in function signature")
# Get the type of the message parameter
target_types = get_types(type_hints["message"])
if target_types is None:
raise AssertionError("Message type not found")
return_types = get_types(type_hints["return"])
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}")View on GitHub (pinned to c028a0c7dc)
Solutions
- Add an explicit return annotation, e.g. -> None or -> ResponseMsg.
- For handlers that return nothing, annotate -> None explicitly.
- Ensure any names in string annotations are imported and resolvable by get_type_hints.
- If using from __future__ import annotations, confirm all referenced types are in scope.
Example fix
// before @message_handler async def handle(self, message: MyMsg, ctx: MessageContext): ... // after @message_handler async def handle(self, message: MyMsg, ctx: MessageContext) -> None: ...
Defensive patterns
Strategy: validation
Validate before calling
from typing import get_type_hints
def handler_has_return_annotation(func) -> bool:
return "return" in get_type_hints(func) Type guard
from typing import get_type_hints, Callable
def handler_has_return(func: Callable) -> bool:
try:
return "return" in get_type_hints(func)
except Exception:
return False Prevention
- Always annotate handler returns (use -> None for no response).
- Ensure string annotations are resolvable.
- Lint handler signatures in CI with get_type_hints checks.
- Import all referenced types at runtime.
When it happens
Trigger: Decorating an async method without a -> annotation, or an annotation that get_type_hints cannot resolve.
Common situations: Omitting the return annotation on a fire-and-forget handler (must still write -> None); PEP 484 string annotations referencing unresolved names.
Related errors
- message parameter not found in function signature
- Message type not found
- Return type not found
- Invalid arguments
- No serializers found for type {msg_type!r}. Please provide a
AI-assisted analysis of microsoft/semantic-kernel@c028a0c7dc (2026-08-13).
Data as JSON: /api/errors/1fb50f088c8079c2.
Report an issue: GitHub.