{"record":{"id":"58ffc1cda97a30d0","repo":"github/copilot-sdk","slug":"waiting-for-session-idle-w","errorCode":null,"errorMessage":"waiting for session.idle: %w","messagePattern":"waiting for session\\.idle: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/session.go","lineNumber":544,"sourceCode":"\t\t}\n\t})\n\tdefer unsubscribe()\n\n\t_, err := s.Send(ctx, options)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tselect {\n\tcase <-idleCh:\n\t\tmu.Lock()\n\t\tresult := lastAssistantMessage\n\t\tmu.Unlock()\n\t\treturn result, nil\n\tcase err := <-errCh:\n\t\treturn nil, err\n\tcase <-ctx.Done():\n\t\treturn nil, fmt.Errorf(\"waiting for session.idle: %w\", ctx.Err())\n\t}\n}\n\n// SendPromptAndWait is a convenience wrapper for [Session.SendAndWait] that\n// takes a plain prompt string instead of a [MessageOptions] struct. Equivalent\n// to:\n//\n//\tsession.SendAndWait(ctx, copilot.MessageOptions{Prompt: prompt})\nfunc (s *Session) SendPromptAndWait(ctx context.Context, prompt string) (*SessionEvent, error) {\n\treturn s.SendAndWait(ctx, MessageOptions{Prompt: prompt})\n}\n\n// On subscribes to events from this session.\n//\n// Events include assistant messages, tool executions, errors, and session state\n// changes. Multiple handlers can be registered and will all receive events.\n// Handlers are called synchronously in the order they were registered.\n//","sourceCodeStart":526,"sourceCodeEnd":562,"githubUrl":"https://github.com/github/copilot-sdk/blob/cd8cf15dc3f9e762615790aaed0a771a0f392755/go/session.go#L526-L562","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Increase the context deadline passed to SendAndWait (e.g. context.WithTimeout with several minutes for agent turns).","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.","If the CLI is genuinely hung, restart the session/client and retry with a longer timeout.","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."],"exampleFix":"// before\nctx, cancel := context.WithTimeout(ctx, 30*time.Second)\nresult, err := session.SendPromptAndWait(ctx, prompt)\n// after\nctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute)\nresult, err := session.SendPromptAndWait(ctx, prompt)","handlingStrategy":"try-catch","validationCode":"if deadline, ok := ctx.Deadline(); ok && time.Until(deadline) < 2*time.Minute {\n    // agent turns can be long; consider extending the deadline\n}","typeGuard":null,"tryCatchPattern":"result, err := session.SendAndWait(ctx, opts)\nif err != nil && errors.Is(err, context.DeadlineExceeded) {\n    // timeout waiting for session.idle: retry with a longer context\n}","preventionTips":["Use generous timeouts (minutes, not seconds) for agent turns","Don't tie the context to short-lived HTTP request contexts","Register permission/user-input handlers so turns never stall awaiting input","Detect err text \"waiting for session.idle\" as a timeout, not a session failure"],"tags":["timeout","context","session"],"backgroundTag":"request-timeout","analyzedSha":"cd8cf15dc3f9e762615790aaed0a771a0f392755","analyzedAt":"2026-09-09T18:32:31.973Z","contentChangedAt":"2026-09-09T18:32:31.973Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}