github/copilot-sdk · error

Invalid exit plan mode request payload

Error message

Invalid exit plan mode request payload

What it means

CopilotClient throws this when an exit-plan-mode request handler receives params that are missing or whose required fields fail type checks: sessionId must be a string, summary a string, actions an array, and recommendedAction a string. The library validates before touching any session state.

Solutions

  1. Ensure actions is always an array (wrap single items in [action]) and summary/recommendedAction are strings.
  2. Include all five required fields: sessionId, summary, actions, recommendedAction (planContent is extra).
  3. Validate the tool/schema output shape before constructing the request payload.
  4. Check for renamed fields after upgrading the library version.

Example fix

// before
client.handleExitPlanModeRequest({ sessionId, summary, actions: plan.steps, recommendedAction: undefined });
// after
client.handleExitPlanModeRequest({
  sessionId,
  summary,
  actions: Array.isArray(plan.steps) ? plan.steps : [plan.steps],
  recommendedAction: plan.recommendedAction ?? plan.steps[0]
});
Defensive patterns

Strategy: validation

Validate before calling

function isValidExitPlanParams(p) {
  return !!p && typeof p.sessionId === "string" &&
    typeof p.summary === "string" && Array.isArray(p.actions) &&
    typeof p.recommendedAction === "string";
}

Type guard

function isExitPlanModeParams(p): p is { sessionId: string; summary: string; actions: unknown[]; recommendedAction: string } {
  return typeof p === "object" && p !== null &&
    typeof (p as any).sessionId === "string" &&
    typeof (p as any).summary === "string" &&
    Array.isArray((p as any).actions) &&
    typeof (p as any).recommendedAction === "string";
}

Try / catch

try {
  await client.handleExitPlanModeRequest(params);
} catch (e) {
  if (e instanceof Error && e.message === "Invalid exit plan mode request payload") {
    // coerce/repair fields then retry once
  }
}

Prevention

When it happens

Trigger: Calling the exit-plan-mode request method with params=null, a non-string sessionId, missing/non-string summary, actions not an array (undefined, object, string), or missing/non-string recommendedAction.

Common situations: Assembling the payload from a tool-call result where actions was a single object instead of an array; forgetting recommendedAction because it is optional in some UI flows; sending plan metadata through a different field name after an API version change.

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/8d34d8557a4f928c. Report an issue: GitHub.

Appendix: source

Thrown at nodejs/src/client.ts:3195

        const result = await session._handleUserInputRequest({
            question: params.question,
            choices: params.choices,
            allowFreeform: params.allowFreeform,
        });
        return result;
    }

    private async handleExitPlanModeRequest(
        params: ExitPlanModeRequest & { sessionId: string }
    ): Promise<ExitPlanModeResult> {
        if (
            !params ||
            typeof params.sessionId !== "string" ||
            typeof params.summary !== "string" ||
            !Array.isArray(params.actions) ||
            typeof params.recommendedAction !== "string"
        ) {
            throw new Error("Invalid exit plan mode request payload");
        }

        const session = this.sessions.get(params.sessionId);
        if (!session) {
            throw new Error(`Session not found: ${params.sessionId}`);
        }

        return await session._handleExitPlanModeRequest({
            summary: params.summary,
            planContent: params.planContent,
            actions: params.actions,
            recommendedAction: params.recommendedAction,
        });
    }

    private async handleAutoModeSwitchRequest(
        params: AutoModeSwitchRequest & { sessionId: string }
    ): Promise<{ response: AutoModeSwitchResponse }> {

View on GitHub (pinned to cd8cf15dc3)