{"record":{"id":"ea2aba554f172ff6","repo":"github/copilot-sdk","slug":"invalid-exit-plan-mode-request-payload-ea2aba","errorCode":null,"errorMessage":"invalid exit plan mode request payload","messagePattern":"invalid exit plan mode request payload","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/copilot/client.py","lineNumber":4963,"sourceCode":"            raise ValueError(\"invalid user input request payload\")\n\n        with self._sessions_lock:\n            session = self._sessions.get(session_id)\n        if not session:\n            raise ValueError(f\"unknown session {session_id}\")\n\n        result = await session._handle_user_input_request(params)\n        return {\"answer\": result[\"answer\"], \"wasFreeform\": result[\"wasFreeform\"]}\n\n    async def _handle_exit_plan_mode_request(self, params: dict) -> dict:\n        \"\"\"Handle an exitPlanMode.request callback from the CLI server.\"\"\"\n        session_id = params.get(\"sessionId\")\n        summary = params.get(\"summary\")\n        actions = params.get(\"actions\")\n        recommended_action = params.get(\"recommendedAction\")\n\n        if not session_id or not isinstance(summary, str):\n            raise ValueError(\"invalid exit plan mode request payload\")\n        if not isinstance(actions, list) or not isinstance(recommended_action, str):\n            raise ValueError(\"invalid exit plan mode request payload\")\n\n        with self._sessions_lock:\n            session = self._sessions.get(session_id)\n        if not session:\n            raise ValueError(f\"unknown session {session_id}\")\n\n        return dict(await session._handle_exit_plan_mode_request(params))\n\n    async def _handle_auto_mode_switch_request(self, params: dict) -> dict:\n        \"\"\"Handle an autoModeSwitch.request callback from the CLI server.\"\"\"\n        session_id = params.get(\"sessionId\")\n        if not session_id:\n            raise ValueError(\"invalid auto mode switch request payload\")\n\n        with self._sessions_lock:\n            session = self._sessions.get(session_id)","sourceCodeStart":4945,"sourceCodeEnd":4981,"githubUrl":"https://github.com/github/copilot-sdk/blob/cd8cf15dc3f9e762615790aaed0a771a0f392755/python/copilot/client.py#L4945-L4981","documentation":"ValueError raised when handling an exitPlanMode request whose payload fails validation: sessionId must be non-empty, summary must be a string, actions must be a list, and recommendedAction must be a string. The check fires twice for the two groups of fields.","triggerScenarios":"CLI server sends an exitPlanMode.request callback with missing/empty sessionId, a non-string summary, a non-list actions field, or a non-string recommendedAction.","commonSituations":"CLI/SDK version drift changing the plan-mode payload schema; custom proxies or test harnesses emitting malformed callbacks; fields renamed in a newer protocol version.","solutions":["Match CLI and SDK versions so plan-mode payloads conform to the expected schema","Dump the incoming params with debug logging to identify the offending field","Update custom middleware that transforms or rebuilds request params","Wrap callback handling to log and skip malformed plan-mode requests instead of crashing"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"def is_valid_exit_plan_params(params: dict) -> bool:\n    return (bool(params.get(\"sessionId\"))\n            and isinstance(params.get(\"summary\"), str)\n            and isinstance(params.get(\"actions\"), list)\n            and isinstance(params.get(\"recommendedAction\"), str))","typeGuard":"def valid_exit_plan(params) -> bool:\n    return (isinstance(params, dict)\n            and bool(params.get(\"sessionId\"))\n            and isinstance(params.get(\"summary\"), str)\n            and isinstance(params.get(\"actions\"), list)\n            and isinstance(params.get(\"recommendedAction\"), str))","tryCatchPattern":"try:\n    await client._handle_exit_plan_mode_request(params)\nexcept ValueError as e:\n    if \"invalid exit plan mode request payload\" in str(e):\n        log.error(\"malformed exitPlanMode.request: %r\", params)\n    else:\n        raise","preventionTips":["Upgrade CLI and SDK together when plan-mode schema changes","Validate exitPlanMode payloads in test harnesses/proxies before forwarding","Log offending payloads to catch protocol drift early","Add schema tests for plan-mode callback fields"],"tags":["validation","payload","plan-mode","rpc"],"backgroundTag":"schema-validation-failed","analyzedSha":"cd8cf15dc3f9e762615790aaed0a771a0f392755","analyzedAt":"2026-09-09T18:32:31.973Z","contentChangedAt":"2026-09-09T18:32:31.973Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}