github/copilot-sdk · error
Invalid hooks invoke payload
Error message
Invalid hooks invoke payload
What it means
CopilotClient throws this when the hooks-invoke handler receives params that are missing, lack a string sessionId, or lack a string hookType. hookType selects which registered hook to run, so the library refuses to proceed without it.
Solutions
- Ensure params = { sessionId: string, hookType: string, input?: unknown } with hookType matching a registered hook name.
- Log the resolved hookType; fix the config/source producing undefined names.
- Validate hook registration list against invoked names before dispatching.
- Unwrap the payload if you are forwarding an enveloped event object.
Example fix
// before
await client.handleHooksInvoke({ sessionId, hookType: cfg.hook?.name, input });
// after
const hookType = cfg.hook?.name;
if (typeof hookType !== "string") throw new Error("hook not configured");
await client.handleHooksInvoke({ sessionId, hookType, input }); Defensive patterns
Strategy: validation
Validate before calling
if (!params || typeof params.sessionId !== "string" || typeof params.hookType !== "string") {
throw new TypeError("hooks invoke requires string sessionId and hookType");
} Type guard
function isHooksInvokeParams(p): p is { sessionId: string; hookType: string; input?: unknown } {
return typeof p === "object" && p !== null &&
typeof (p as any).sessionId === "string" && typeof (p as any).hookType === "string";
} Try / catch
try {
await client.handleHooksInvoke(params);
} catch (e) {
if (e instanceof Error && e.message === "Invalid hooks invoke payload") {
// log configured hookType and skip this hook
}
} Prevention
- Keep hook names in a typed constant union instead of free-form config strings.
- Validate hook config at startup; fail fast on missing names.
- Never pass the hook config object itself as the params payload.
When it happens
Trigger: Calling the hooks-invoke method with params null/undefined, sessionId not a string, or hookType missing/not a string (e.g. passing input object first or hookType undefined).
Common situations: Hook dispatcher built from config where the hook name key is misspelled; passing the whole hook config object as params instead of {sessionId, hookType, input}; dynamic hook names resolved to undefined at runtime.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- Invalid user input request payload
- Invalid exit plan mode request payload
- Invalid auto mode switch request 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/b847605be331816d.
Report an issue: GitHub.
Appendix: source
Thrown at nodejs/src/client.ts:3240
const response = await session._handleAutoModeSwitchRequest({
errorCode: params.errorCode,
retryAfterSeconds: params.retryAfterSeconds,
});
return { response };
}
private async handleHooksInvoke(params: {
sessionId: string;
hookType: string;
input: unknown;
}): Promise<{ output?: unknown }> {
if (
!params ||
typeof params.sessionId !== "string" ||
typeof params.hookType !== "string"
) {
throw new Error("Invalid hooks invoke payload");
}
const session = this.sessions.get(params.sessionId);
if (!session) {
throw new Error(`Session not found: ${params.sessionId}`);
}
const output = await session._handleHooksInvoke(params.hookType, params.input);
return { output };
}
private async handleSystemMessageTransform(params: {
sessionId: string;
sections: Record<string, { content: string }>;
}): Promise<{ sections: Record<string, { content: string }> }> {
if (
!params ||
typeof params.sessionId !== "string" ||View on GitHub (pinned to cd8cf15dc3)