github/copilot-sdk · error · ValueError

invalid exit plan mode request payload

Error message

invalid exit plan mode request payload

What it means

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.

Solutions

  1. Match CLI and SDK versions so plan-mode payloads conform to the expected schema
  2. Dump the incoming params with debug logging to identify the offending field
  3. Update custom middleware that transforms or rebuilds request params
  4. Wrap callback handling to log and skip malformed plan-mode requests instead of crashing
Defensive patterns

Strategy: validation

Validate before calling

def is_valid_exit_plan_params(params: dict) -> bool:
    return (bool(params.get("sessionId"))
            and isinstance(params.get("summary"), str)
            and isinstance(params.get("actions"), list)
            and isinstance(params.get("recommendedAction"), str))

Type guard

def valid_exit_plan(params) -> bool:
    return (isinstance(params, dict)
            and bool(params.get("sessionId"))
            and isinstance(params.get("summary"), str)
            and isinstance(params.get("actions"), list)
            and isinstance(params.get("recommendedAction"), str))

Try / catch

try:
    await client._handle_exit_plan_mode_request(params)
except ValueError as e:
    if "invalid exit plan mode request payload" in str(e):
        log.error("malformed exitPlanMode.request: %r", params)
    else:
        raise

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of github/copilot-sdk@cd8cf15dc3 (2026-09-09). Data as JSON: /api/errors/ea2aba554f172ff6. Report an issue: GitHub.

Appendix: source

Thrown at python/copilot/client.py:4963

            raise ValueError("invalid user input request payload")

        with self._sessions_lock:
            session = self._sessions.get(session_id)
        if not session:
            raise ValueError(f"unknown session {session_id}")

        result = await session._handle_user_input_request(params)
        return {"answer": result["answer"], "wasFreeform": result["wasFreeform"]}

    async def _handle_exit_plan_mode_request(self, params: dict) -> dict:
        """Handle an exitPlanMode.request callback from the CLI server."""
        session_id = params.get("sessionId")
        summary = params.get("summary")
        actions = params.get("actions")
        recommended_action = params.get("recommendedAction")

        if not session_id or not isinstance(summary, str):
            raise ValueError("invalid exit plan mode request payload")
        if not isinstance(actions, list) or not isinstance(recommended_action, str):
            raise ValueError("invalid exit plan mode request payload")

        with self._sessions_lock:
            session = self._sessions.get(session_id)
        if not session:
            raise ValueError(f"unknown session {session_id}")

        return dict(await session._handle_exit_plan_mode_request(params))

    async def _handle_auto_mode_switch_request(self, params: dict) -> dict:
        """Handle an autoModeSwitch.request callback from the CLI server."""
        session_id = params.get("sessionId")
        if not session_id:
            raise ValueError("invalid auto mode switch request payload")

        with self._sessions_lock:
            session = self._sessions.get(session_id)

View on GitHub (pinned to cd8cf15dc3)