{"record":{"id":"45e57c6687231b12","repo":"microsoft/autogen","slug":"selector-function-returned-an-invalid-speaker-name","errorCode":null,"errorMessage":"Selector function returned an invalid speaker name: {speaker}. Expected one of: {self._participant_names}.","messagePattern":"Selector function returned an invalid speaker name: (.+?)\\. Expected one of: (.+?)\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/packages/autogen-agentchat/src/autogen_agentchat/teams/_group_chat/_selector_group_chat.py","lineNumber":172,"sourceCode":"        with the selector function as override if it returns a speaker name.\n\n        .. note::\n\n            This method always returns a single speaker name.\n\n        A key assumption is that the agent type is the same as the topic type, which we use as the agent name.\n        \"\"\"\n        # Use the selector function if provided.\n        if self._selector_func is not None:\n            if self._is_selector_func_async:\n                async_selector_func = cast(AsyncSelectorFunc, self._selector_func)\n                speaker = await async_selector_func(thread)\n            else:\n                sync_selector_func = cast(SyncSelectorFunc, self._selector_func)\n                speaker = sync_selector_func(thread)\n            if speaker is not None:\n                if speaker not in self._participant_names:\n                    raise ValueError(\n                        f\"Selector function returned an invalid speaker name: {speaker}. \"\n                        f\"Expected one of: {self._participant_names}.\"\n                    )\n                # Skip the model based selection.\n                return [speaker]\n\n        # Use the candidate function to filter participants if provided\n        if self._candidate_func is not None:\n            if self._is_candidate_func_async:\n                async_candidate_func = cast(AsyncCandidateFunc, self._candidate_func)\n                participants = await async_candidate_func(thread)\n            else:\n                sync_candidate_func = cast(SyncCandidateFunc, self._candidate_func)\n                participants = sync_candidate_func(thread)\n            if not participants:\n                raise ValueError(\"Candidate function must return a non-empty list of participant names.\")\n            if not all(p in self._participant_names for p in participants):\n                raise ValueError(","sourceCodeStart":154,"sourceCodeEnd":190,"githubUrl":"https://github.com/microsoft/autogen/blob/027ecf0a379bcc1d09956d46d12d44a3ad9cee14/python/packages/autogen-agentchat/src/autogen_agentchat/teams/_group_chat/_selector_group_chat.py#L154-L190","documentation":"SelectorGroupChatManager raises ValueError when a user-supplied selector_func returns a speaker name that is not in the team's participant names. The selector function bypasses model-based selection, so its return value must exactly match a participant name (or be None to fall through).","triggerScenarios":"selector_func(thread) returns a hardcoded string like \"assistant\" while the participants are named differently; returning the agent object instead of its .name; case/whitespace mismatch in the returned name.","commonSituations":"Writing a custom selector_func before finalizing agent names; refactoring agent names without updating the selector; returning '' or a placeholder instead of None to skip selection.","solutions":["Return the exact participant name string (agent.name) from selector_func.","Return None when you want the manager to fall through to model-based/candidate selection instead of an invalid name.","Derive names from the participants list rather than hardcoding: return next(p.name for p in participants if <condition>)."],"exampleFix":"# before\ndef selector(thread):\n    return \"assistant\"  # no participant named 'assistant'\n\n# after\ndef selector(thread):\n    if thread and thread[-1].source == \"researcher\":\n        return \"coder\"  # exact participant name, or None to skip\n    return None","handlingStrategy":"validation","validationCode":"def make_selector(participant_names: list[str]):\n    def selector(thread):\n        name = pick_name(thread)\n        return name if name in participant_names else None\n    return selector","typeGuard":"def is_valid_speaker(name: str | None, participant_names: Sequence[str]) -> bool:\n    return name is None or name in participant_names","tryCatchPattern":null,"preventionTips":["Derive returned names from the participants list, never hardcode strings.","Return None to fall through to model-based selection instead of guessing."],"tags":["autogen","selector","selector-func","validation"],"backgroundTag":null,"analyzedSha":"027ecf0a379bcc1d09956d46d12d44a3ad9cee14","analyzedAt":"2026-08-15T03:38:00.719Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}