{"record":{"id":"e7f8b42d8efec246","repo":"github/copilot-sdk","slug":"invalid-user-input-request-payload","errorCode":null,"errorMessage":"Invalid user input request payload","messagePattern":"Invalid user input request payload","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nodejs/src/client.ts","lineNumber":3169,"sourceCode":"                handler(event);\n            } catch {\n                // Ignore handler errors\n            }\n        }\n    }\n\n    private async handleUserInputRequest(params: {\n        sessionId: string;\n        question: string;\n        choices?: string[];\n        allowFreeform?: boolean;\n    }): Promise<{ answer: string; wasFreeform: boolean }> {\n        if (\n            !params ||\n            typeof params.sessionId !== \"string\" ||\n            typeof params.question !== \"string\"\n        ) {\n            throw new Error(\"Invalid user input 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        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> {","sourceCodeStart":3151,"sourceCodeEnd":3187,"githubUrl":"https://github.com/github/copilot-sdk/blob/cd8cf15dc3f9e762615790aaed0a771a0f392755/nodejs/src/client.ts#L3151-L3187","documentation":"CopilotClient throws this when a user-input request handler receives a params object that is missing or whose sessionId/question fields are not strings. The library validates the payload shape before doing any work so it can fail fast instead of dispatching to a session with garbage data. It is a synchronous guard at the public API boundary.","triggerScenarios":"Calling the client's user-input request method (the handler at nodejs/src/client.ts:3169) with params=null/undefined, params.sessionId not a string (missing, number, object), or params.question not a string.","commonSituations":"Forwarding a deserialized JSON message where sessionId/question were absent or typed as numbers; building the params object dynamically and forgetting question; passing the raw event object instead of the extracted fields.","solutions":["Ensure params is an object containing both sessionId and question as non-empty strings before calling the method.","Validate/coerce the payload where it is deserialized (e.g. after JSON.parse) rather than at call time.","Check that the caller passes fields individually and not a nested object (e.g. params.message.sessionId)."],"exampleFix":"// before\nawait client.handleUserInputRequest({ sessionId: msg.sid, question: undefined });\n// after\nif (typeof msg.sid !== \"string\" || typeof msg.question !== \"string\") return;\nawait client.handleUserInputRequest({ sessionId: msg.sid, question: msg.question });","handlingStrategy":"validation","validationCode":"function canSendUserInput(p) {\n  return !!p && typeof p.sessionId === \"string\" && typeof p.question === \"string\";\n}","typeGuard":"function isUserInputParams(p): p is { sessionId: string; question: string; choices?: string[]; allowFreeform?: boolean } {\n  return typeof p === \"object\" && p !== null &&\n    typeof (p as any).sessionId === \"string\" && typeof (p as any).question === \"string\";\n}","tryCatchPattern":"try {\n  await client.handleUserInputRequest(params);\n} catch (e) {\n  if (e instanceof Error && e.message === \"Invalid user input request payload\") {\n    // fix/serialize payload, do not retry blindly\n  }\n}","preventionTips":["Define a shared typed params interface and construct it via one factory function.","Validate payloads at the deserialization boundary (zod/ajv) before they reach client calls.","Never forward raw event objects; extract and check fields explicitly."],"tags":["validation","payload","typescript","api-boundary"],"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"}