github/copilot-sdk · error

waiting for session.idle

Error message

waiting for session.idle: %w

What it means

SendAndWait blocks until either the assistant's final message arrives, a session error event fires, or the caller's context is done. When the context deadline or cancellation fires before the session reaches idle, the library wraps ctx.Err() with this message and returns it. It means the turn did not complete within the caller's allotted time.

Solutions

  1. Increase the context deadline passed to SendAndWait (e.g. context.WithTimeout with several minutes for agent turns).
  2. Don't derive the context from a short-lived request context if you need the turn to finish; use context.Background() with your own timeout.
  3. If the CLI is genuinely hung, restart the session/client and retry with a longer timeout.
  4. Check for in-flight tool calls or permission prompts blocking completion (e.g. no registered permission/user-input handler) that stall the turn until the deadline.

Example fix

// before
ctx, cancel := context.WithTimeout(ctx, 30*time.Second)
result, err := session.SendPromptAndWait(ctx, prompt)
// after
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute)
result, err := session.SendPromptAndWait(ctx, prompt)
Defensive patterns

Strategy: try-catch

Validate before calling

if deadline, ok := ctx.Deadline(); ok && time.Until(deadline) < 2*time.Minute {
    // agent turns can be long; consider extending the deadline
}

Try / catch

result, err := session.SendAndWait(ctx, opts)
if err != nil && errors.Is(err, context.DeadlineExceeded) {
    // timeout waiting for session.idle: retry with a longer context
}

Prevention

When it happens

Trigger: Calling Session.SendAndWait or Session.SendPromptAndWait with a context whose deadline elapses (or is cancelled) while the CLI is still generating the response — e.g. context.WithTimeout(ctx, 30*time.Second) on a long generation.

Common situations: Long-running agent turns exceeding an HTTP-server request timeout; a request.Context() cancelled when an HTTP client disconnects; overly tight timeouts in tests; CLI stuck or hung producing no completion event.

Understand the failure class

Background: Request timed out: what client-side request timeouts mean across libraries (Request timed out, TIMED_OUT, APITimeoutError) — this error's family across 39 libraries.

Related errors


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

Appendix: source

Thrown at go/session.go:544

		}
	})
	defer unsubscribe()

	_, err := s.Send(ctx, options)
	if err != nil {
		return nil, err
	}

	select {
	case <-idleCh:
		mu.Lock()
		result := lastAssistantMessage
		mu.Unlock()
		return result, nil
	case err := <-errCh:
		return nil, err
	case <-ctx.Done():
		return nil, fmt.Errorf("waiting for session.idle: %w", ctx.Err())
	}
}

// SendPromptAndWait is a convenience wrapper for [Session.SendAndWait] that
// takes a plain prompt string instead of a [MessageOptions] struct. Equivalent
// to:
//
//	session.SendAndWait(ctx, copilot.MessageOptions{Prompt: prompt})
func (s *Session) SendPromptAndWait(ctx context.Context, prompt string) (*SessionEvent, error) {
	return s.SendAndWait(ctx, MessageOptions{Prompt: prompt})
}

// On subscribes to events from this session.
//
// Events include assistant messages, tool executions, errors, and session state
// changes. Multiple handlers can be registered and will all receive events.
// Handlers are called synchronously in the order they were registered.
//

View on GitHub (pinned to cd8cf15dc3)