github/copilot-sdk · error
failed to send message
Error message
failed to send message: %w
What it means
Session.Send issues a "session.send" request over the client's transport. If that request fails (transport error, non-success response, timeout), the error is wrapped as "failed to send message". The empty string message ID is returned since no response arrived.
Solutions
- Inspect the wrapped inner error to distinguish transport failure vs server rejection.
- Check that the agent server is running and the session is still connected (session.Disconnect/Reconnect as needed).
- Increase the context timeout for large prompts or slow networks.
- Retry the send with backoff if the inner error is transient (connection reset, timeout).
Example fix
// before ctx := context.Background() id, err := session.Send(ctx, msg) // hangs/fails on slow networks // after ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() id, err := session.Send(ctx, msg)
Defensive patterns
Strategy: retry
Try / catch
var id string
var err error
for i := 0; i < 3; i++ {
id, err = session.Send(ctx, msg, opts)
if err == nil || !isTransient(err) {
break
}
time.Sleep(time.Duration(1<<i) * 100 * time.Millisecond)
} Prevention
- Set generous context timeouts for sends
- Health-check the server before sending
- Handle session disconnections with reconnect logic
When it happens
Trigger: s.client.Request(ctx, "session/send", req) returns an error during Send (directly or via SendPrompt/SendAndWait) — connection drop, server unavailable, context deadline exceeded, or authentication failure.
Common situations: Server process stopped or crashed; network interruption mid-session; context deadline too short for large prompts; session already closed on the server.
Understand the failure class
Background: "API request failed": what wrapped HTTP errors from external APIs mean and how to find the real cause — this error's family across 29 libraries.
Related errors
- failed to create session
- failed to resume session
- failed to get events
- No session found for sessionId
- Copilot request response used after RPC connection closed.
AI-assisted analysis of github/copilot-sdk@cd8cf15dc3 (2026-09-09).
Data as JSON: /api/errors/912bf476764660b8.
Report an issue: GitHub.
Appendix: source
Thrown at go/session.go:447
// }
func (s *Session) Send(ctx context.Context, options MessageOptions) (string, error) {
traceparent, tracestate := getTraceContext(ctx)
req := sessionSendRequest{
SessionID: s.SessionID,
Prompt: options.Prompt,
Source: options.Source,
DisplayPrompt: options.DisplayPrompt,
Attachments: options.Attachments,
Mode: options.Mode,
AgentMode: options.AgentMode,
Traceparent: traceparent,
Tracestate: tracestate,
RequestHeaders: options.RequestHeaders,
}
result, err := s.client.Request(ctx, "session.send", req)
if err != nil {
return "", fmt.Errorf("failed to send message: %w", err)
}
var response sessionSendResponse
if err := json.Unmarshal(result, &response); err != nil {
return "", fmt.Errorf("failed to unmarshal send response: %w", err)
}
return response.MessageID, nil
}
// SendPrompt is a convenience wrapper for [Session.Send] that takes a plain
// prompt string instead of a [MessageOptions] struct. Equivalent to:
//
// session.Send(ctx, copilot.MessageOptions{Prompt: prompt})
func (s *Session) SendPrompt(ctx context.Context, prompt string) (string, error) {
return s.Send(ctx, MessageOptions{Prompt: prompt})
}
// SendAndWait sends a message to this session and waits until the session becomes idle.View on GitHub (pinned to cd8cf15dc3)