{"record":{"id":"8d34d8557a4f928c","repo":"github/copilot-sdk","slug":"invalid-exit-plan-mode-request-payload","errorCode":null,"errorMessage":"Invalid exit plan mode request payload","messagePattern":"Invalid exit plan mode request payload","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nodejs/src/client.ts","lineNumber":3195,"sourceCode":"        const result = await session._handleUserInputRequest({\n            question: params.question,\n            choices: params.choices,\n            allowFreeform: params.allowFreeform,\n        });\n        return result;\n    }\n\n    private async handleExitPlanModeRequest(\n        params: ExitPlanModeRequest & { sessionId: string }\n    ): Promise<ExitPlanModeResult> {\n        if (\n            !params ||\n            typeof params.sessionId !== \"string\" ||\n            typeof params.summary !== \"string\" ||\n            !Array.isArray(params.actions) ||\n            typeof params.recommendedAction !== \"string\"\n        ) {\n            throw new Error(\"Invalid exit plan mode request payload\");\n        }\n\n        const session = this.sessions.get(params.sessionId);\n        if (!session) {\n            throw new Error(`Session not found: ${params.sessionId}`);\n        }\n\n        return await session._handleExitPlanModeRequest({\n            summary: params.summary,\n            planContent: params.planContent,\n            actions: params.actions,\n            recommendedAction: params.recommendedAction,\n        });\n    }\n\n    private async handleAutoModeSwitchRequest(\n        params: AutoModeSwitchRequest & { sessionId: string }\n    ): Promise<{ response: AutoModeSwitchResponse }> {","sourceCodeStart":3177,"sourceCodeEnd":3213,"githubUrl":"https://github.com/github/copilot-sdk/blob/cd8cf15dc3f9e762615790aaed0a771a0f392755/nodejs/src/client.ts#L3177-L3213","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nclient.handleExitPlanModeRequest({ sessionId, summary, actions: plan.steps, recommendedAction: undefined });\n// after\nclient.handleExitPlanModeRequest({\n  sessionId,\n  summary,\n  actions: Array.isArray(plan.steps) ? plan.steps : [plan.steps],\n  recommendedAction: plan.recommendedAction ?? plan.steps[0]\n});","handlingStrategy":"validation","validationCode":"function isValidExitPlanParams(p) {\n  return !!p && typeof p.sessionId === \"string\" &&\n    typeof p.summary === \"string\" && Array.isArray(p.actions) &&\n    typeof p.recommendedAction === \"string\";\n}","typeGuard":"function isExitPlanModeParams(p): p is { sessionId: string; summary: string; actions: unknown[]; recommendedAction: string } {\n  return typeof p === \"object\" && p !== null &&\n    typeof (p as any).sessionId === \"string\" &&\n    typeof (p as any).summary === \"string\" &&\n    Array.isArray((p as any).actions) &&\n    typeof (p as any).recommendedAction === \"string\";\n}","tryCatchPattern":"try {\n  await client.handleExitPlanModeRequest(params);\n} catch (e) {\n  if (e instanceof Error && e.message === \"Invalid exit plan mode request payload\") {\n    // coerce/repair fields then retry once\n  }\n}","preventionTips":["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."],"tags":["validation","payload","plan-mode","typescript"],"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"}