github/copilot-sdk · error

failed to unmarshal get events response

Error message

failed to unmarshal get events response: %w

What it means

After the `session.getMessages` RPC succeeds, GetEvents unmarshals the result payload into sessionGetMessagesResponse. This error means the response JSON could not be decoded into that struct — the runtime returned data that does not match the SDK's expected event-response shape.

Solutions

  1. Upgrade the Go SDK and the runtime/CLI to matching versions
  2. Log the raw `result` payload to inspect the actual response shape
  3. Check for a proxy/interceptor altering the response
  4. Report the mismatch if the runtime is current and shapes still differ

Example fix

// before
events, err := session.GetEvents(ctx)
// after
events, err := session.GetEvents(ctx)
if err != nil && strings.Contains(err.Error(), "unmarshal get events") {
    log.Fatalf("runtime/SDK version mismatch on getMessages payload: %v", err)
}
Defensive patterns

Strategy: try-catch

Try / catch

events, err := session.GetEvents(ctx)
if err != nil && strings.Contains(err.Error(), "unmarshal") {
    log.Printf("response shape mismatch (SDK/runtime version skew?): %v", err)
}

Prevention

When it happens

Trigger: Calling Session.GetEvents when the runtime's reply for `session.getMessages` has fields with unexpected types or an incompatible schema (json.Unmarshal into sessionGetMessagesResponse fails).

Common situations: SDK version older/newer than the running runtime so the messages payload shape differs; a proxy or patched runtime returning non-standard JSON; corrupted payload over the transport.

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/5735b5a2eaedb753. Report an issue: GitHub.

Appendix: source

Thrown at go/session.go:1808

//	if err != nil {
//	    log.Printf("Failed to get events: %v", err)
//	    return
//	}
//	for _, event := range events {
//	    if d, ok := event.Data.(*copilot.AssistantMessageData); ok {
//	        fmt.Println("Assistant:", d.Content)
//	    }
//	}
func (s *Session) GetEvents(ctx context.Context) ([]SessionEvent, error) {

	result, err := s.client.Request(ctx, "session.getMessages", sessionGetMessagesRequest{SessionID: s.SessionID})
	if err != nil {
		return nil, fmt.Errorf("failed to get events: %w", err)
	}

	var response sessionGetMessagesResponse
	if err := json.Unmarshal(result, &response); err != nil {
		return nil, fmt.Errorf("failed to unmarshal get events response: %w", err)
	}
	return response.Events, nil
}

// Disconnect closes this session and releases all in-memory resources (event
// handlers, tool handlers, permission handlers).
//
// The caller should ensure the session is idle (e.g., [Session.SendAndWait] has
// returned) before disconnecting. If the session is not idle, in-flight event
// handlers or tool handlers may observe failures.
//
// Session state on disk (conversation history, planning state, artifacts) is
// preserved, so the conversation can be resumed later by calling
// [Client.ResumeSession] with the session ID. To permanently remove all
// session data including files on disk, use [Client.DeleteSession] instead.
//
// After calling this method, the session object can no longer be used.
//

View on GitHub (pinned to cd8cf15dc3)