github/copilot-sdk · error
Invalid user input request payload
Error message
Invalid user input request payload
What it means
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.
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).
Example fix
// before
await client.handleUserInputRequest({ sessionId: msg.sid, question: undefined });
// after
if (typeof msg.sid !== "string" || typeof msg.question !== "string") return;
await client.handleUserInputRequest({ sessionId: msg.sid, question: msg.question }); Defensive patterns
Strategy: validation
Validate before calling
function canSendUserInput(p) {
return !!p && typeof p.sessionId === "string" && typeof p.question === "string";
} Type guard
function isUserInputParams(p): p is { sessionId: string; question: string; choices?: string[]; allowFreeform?: boolean } {
return typeof p === "object" && p !== null &&
typeof (p as any).sessionId === "string" && typeof (p as any).question === "string";
} Try / catch
try {
await client.handleUserInputRequest(params);
} catch (e) {
if (e instanceof Error && e.message === "Invalid user input request payload") {
// fix/serialize payload, do not retry blindly
}
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
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 exit plan mode request payload
- Invalid auto mode switch request payload
- Invalid hooks invoke payload
- Invalid systemMessage.transform payload
- Factory limit "timeoutSeconds" must be a positive, finite…
AI-assisted analysis of github/copilot-sdk@cd8cf15dc3 (2026-09-09).
Data as JSON: /api/errors/e7f8b42d8efec246.
Report an issue: GitHub.
Appendix: source
Thrown at nodejs/src/client.ts:3169
handler(event);
} catch {
// Ignore handler errors
}
}
}
private async handleUserInputRequest(params: {
sessionId: string;
question: string;
choices?: string[];
allowFreeform?: boolean;
}): Promise<{ answer: string; wasFreeform: boolean }> {
if (
!params ||
typeof params.sessionId !== "string" ||
typeof params.question !== "string"
) {
throw new Error("Invalid user input request payload");
}
const session = this.sessions.get(params.sessionId);
if (!session) {
throw new Error(`Session not found: ${params.sessionId}`);
}
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> {View on GitHub (pinned to cd8cf15dc3)