{"record":{"id":"271d85928c49c44c","repo":"microsoft/autogen","slug":"candidate-function-returned-invalid-participant-na","errorCode":null,"errorMessage":"Candidate function returned invalid participant names: {participants}. Expected one of: {self._participant_names}.","messagePattern":"Candidate function returned invalid participant names: (.+?)\\. 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":190,"sourceCode":"                    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(\n                    f\"Candidate function returned invalid participant names: {participants}. \"\n                    f\"Expected one of: {self._participant_names}.\"\n                )\n        else:\n            # Construct the candidate agent list to be selected from, skip the previous speaker if not allowed.\n            if self._previous_speaker is not None and not self._allow_repeated_speaker:\n                participants = [p for p in self._participant_names if p != self._previous_speaker]\n            else:\n                participants = list(self._participant_names)\n\n        assert len(participants) > 0\n\n        # Construct agent roles.\n        # Each agent sould appear on a single line.\n        roles = \"\"\n        for topic_type, description in zip(self._participant_names, self._participant_descriptions, strict=True):\n            roles += re.sub(r\"\\s+\", \" \", f\"{topic_type}: {description}\").strip() + \"\\n\"\n        roles = roles.strip()","sourceCodeStart":172,"sourceCodeEnd":208,"githubUrl":"https://github.com/microsoft/autogen/blob/027ecf0a379bcc1d09956d46d12d44a3ad9cee14/python/packages/autogen-agentchat/src/autogen_agentchat/teams/_group_chat/_selector_group_chat.py#L172-L208","documentation":"SelectorGroupChatManager raises ValueError when candidate_func returns names that are not all members of the team's participant names. Like selector_func, the candidate function operates on name strings that must exactly match registered participants.","triggerScenarios":"candidate_func returns names from a stale/hardcoded list, an agent object's repr, or names with typos/case differences relative to the actual participants.","commonSituations":"Hardcoding candidate names at module level then renaming agents later; building candidates from a different team's participant list; mixing display names with agent.name values.","solutions":["Intersect returned names with the real participant set: [n for n in result if n in participant_names] and ensure the result is non-empty.","Derive candidate names from the same agents passed to SelectorGroupChat, not from a separate constant.","Add an assert all(n in participant_names for n in result) inside your candidate function during development."],"exampleFix":"# before\nCANDIDATES = [\"writer\", \"critic\"]  # stale; team has 'coder' not 'writer'\ndef candidates(thread):\n    return CANDIDATES\n\n# after\nparticipant_names = [a.name for a in agents]\ndef candidates(thread):\n    wanted = [\"coder\", \"critic\"]\n    return [n for n in wanted if n in participant_names] or participant_names","handlingStrategy":"validation","validationCode":"def candidates(thread):\n    wanted = compute_wanted(thread)\n    valid = [n for n in wanted if n in participant_names]\n    return valid if valid else list(participant_names)","typeGuard":"def all_valid_participants(names: Sequence[str], participant_names: Sequence[str]) -> bool:\n    return all(n in participant_names for n in names)","tryCatchPattern":null,"preventionTips":["Intersect any computed candidate list with the live participant set.","Regenerate hardcoded name lists whenever participants change."],"tags":["autogen","selector","candidate-func","validation"],"backgroundTag":null,"analyzedSha":"027ecf0a379bcc1d09956d46d12d44a3ad9cee14","analyzedAt":"2026-08-15T03:38:00.719Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}