chenhg5/cc-connect · error
ping timeout
Error message
ping timeout
What it means
Handshake step 1 waits up to 10 seconds for the `ping` response. If the timer fires first (no reply, no context cancellation), handshake returns the literal error "ping timeout". It means the copilot process is alive or hung but its JSON-RPC loop is not answering.
Source
Thrown at agent/copilot/session.go:169
if err := cs.handshake(resumeSessionID); err != nil {
_ = cs.Close()
return nil, fmt.Errorf("copilotSession: handshake failed: %w", err)
}
return cs, nil
}
func (cs *copilotSession) handshake(resumeSessionID string) error {
// Step 1: Ping
_, pingCh := cs.rpc.call("ping", nil)
select {
case resp := <-pingCh:
if resp.Error != nil {
return fmt.Errorf("ping: %w", resp.Error)
}
slog.Debug("copilotSession: ping OK")
case <-time.After(10 * time.Second):
return fmt.Errorf("ping timeout")
case <-cs.ctx.Done():
return cs.ctx.Err()
}
// Step 2: Create or resume session
if resumeSessionID != "" && resumeSessionID != core.ContinueSession {
_, resumeCh := cs.rpc.call("session.resume", cs.sessionConfig(resumeSessionID))
select {
case resp := <-resumeCh:
if resp.Error != nil {
slog.Warn("copilotSession: resume failed, creating new session", "error", resp.Error)
return cs.createSession()
}
cs.sessionID.Store(resumeSessionID)
slog.Info("copilotSession: session resumed", "sessionId", resumeSessionID)
case <-time.After(10 * time.Second):
return fmt.Errorf("session.resume timeout")
case <-cs.ctx.Done():View on GitHub (pinned to 4000b2338a)
Solutions
- Check the copilot CLI stderr buffer for interactive prompts (login prompts hang the handshake)
- Run the CLI manually to confirm it starts non-interactively and answers requests
- If cold start is slow in your environment, this timeout is the guard — pre-warm the agent or accept the failure and retry
- Verify stdout is pure LSP-framed JSON-RPC (a framing bug makes every read hang) — see readMessage errors
- Increase the 10s timeout in session.go only after confirming the child is genuinely slow, not hung
Example fix
// before: CLI launches interactively and hangs child := exec.Command(binPath) // prompts "sign in?" on first run // after: pre-authenticate so startup never blocks on stdin // run once as the daemon user: copilot auth login child := exec.Command(binPath, "--headless") // or equivalent non-interactive flag
Defensive patterns
Strategy: retry
Validate before calling
// ensure the CLI can start and respond non-interactively before session creation
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
out, err := exec.CommandContext(ctx, copilotPath, "--version").Output()
cancel()
if err != nil || len(bytes.TrimSpace(out)) == 0 {
return fmt.Errorf("copilot CLI unresponsive/interactive: %w", err)
} Try / catch
sess, err := StartSession(ctx, cfg, resumeID)
if err != nil {
if strings.Contains(err.Error(), "ping timeout") {
// one retry; repeated timeouts mean the CLI hangs and needs diagnosis
if attempt++; attempt < 2 {
return StartSession(ctx, cfg, "")
}
return fmt.Errorf("copilot ping timeout after retry: %w", err)
}
return err
} Prevention
- Guarantee non-interactive startup (pre-auth, no prompts) for the daemon user
- Ensure stdout stays pure JSON-RPC — stderr is where logs belong
- Keep stderr drained (reader goroutine) so the child never blocks on a full pipe
- Raise the 10s timeout only on hosts with proven slow cold starts; investigate hangs instead
When it happens
Trigger: handshake() from newCopilotSession: no ping response arrives on pingCh within time.After(10*time.Second) — reader goroutine stuck, child process hung, output not LSP-framed so the reader never completes a message, or the CLI is blocked on auth/network.
Common situations: Copilot CLI waiting for interactive login on stdout/stdin; child stuck due to a full stderr/stdout pipe; a very slow cold start exceeding 10s; output framing mismatch so readLoop can't parse any message; CI machines with heavy startup latency.
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.
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- copilotSession: handshake failed: %w
- copilot: session.delete: %s
- copilot: session.delete failed: %s
- copilot: session.delete failed: unknown error
- ping: %w
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/3a453cc5ac563dbe.
Report an issue: GitHub.