github/copilot-sdk · error

invalid hook input

Error message

invalid hook input: %w

What it means

In handleHooksInvoke, when the CLI delivers a preToolUse hook callback, the raw JSON payload is unmarshalled into PreToolUseHookInput. If the JSON does not match the expected schema, the SDK returns this error wrapping the json.Unmarshal error instead of invoking the registered OnPreToolUse hook.

Solutions

  1. Upgrade the Go SDK and the Copilot CLI to matching versions so the PreToolUseHookInput schema lines up.
  2. Log the raw input payload (enable debug logging) and compare it to the PreToolUseHookInput struct fields.
  3. Check that your hooks registration (OnPreToolUse) is configured for the correct hook type string.
Defensive patterns

Strategy: try-catch

Try / catch

out, err := session.handleHooksInvoke("preToolUse", raw)
if err != nil && strings.HasPrefix(err.Error(), "invalid hook input:") {
    // schema mismatch: log raw payload, check SDK/CLI versions
}

Prevention

When it happens

Trigger: A preToolUse hooksInvoke request whose req.Input JSON fails to decode into PreToolUseHookInput (wrong/missing fields, wrong types, malformed JSON).

Common situations: SDK and CLI versions disagree on the hook payload schema; CLI update adds/renames fields with different types; a custom/older CLI binary sending non-conformant input.

Understand the failure class

Background: "failed to unmarshal" / json.Unmarshal errors: why parsing a response into a Go struct fails and how to fix it — this error's family across 23 libraries.

Related errors


AI-assisted analysis of github/copilot-sdk@cd8cf15dc3 (2026-09-09). Data as JSON: /api/errors/64c9bd5d03798bba. Report an issue: GitHub.

Appendix: source

Thrown at go/session.go:764

func (s *Session) handleHooksInvoke(hookType string, rawInput json.RawMessage) (any, error) {
	hooks := s.getHooks()

	if hooks == nil {
		return nil, nil
	}

	invocation := HookInvocation{
		SessionID: s.SessionID,
	}

	switch hookType {
	case "preToolUse":
		if hooks.OnPreToolUse == nil {
			return nil, nil
		}
		var input PreToolUseHookInput
		if err := json.Unmarshal(rawInput, &input); err != nil {
			return nil, fmt.Errorf("invalid hook input: %w", err)
		}
		return hooks.OnPreToolUse(input, invocation)

	case "preMcpToolCall":
		if hooks.OnPreMCPToolCall == nil {
			return nil, nil
		}
		var input PreMCPToolCallHookInput
		if err := json.Unmarshal(rawInput, &input); err != nil {
			return nil, fmt.Errorf("invalid hook input: %w", err)
		}
		return hooks.OnPreMCPToolCall(input, invocation)

	case "postToolUse":
		if hooks.OnPostToolUse == nil {
			return nil, nil
		}
		var input PostToolUseHookInput

View on GitHub (pinned to cd8cf15dc3)