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
- Ensure actions is always an array (wrap single items in [action]) and summary/recommendedAction are strings.
- Include all five required fields: sessionId, summary, actions, recommendedAction (planContent is extra).
- Validate the tool/schema output shape before constructing the request payload.
- 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
- Always wrap single action items into an array before sending.
- Provide a default for recommendedAction in plan-generation code.
- Schema-validate tool outputs before converting them to request payloads.
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
- Invalid user input request payload
- Invalid auto mode switch request payload
- Invalid hooks invoke payload
- Invalid systemMessage.transform payload
- invalid exit plan mode request payload
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)