{"record":{"id":"c75ce87fb7bd7de0","repo":"chenhg5/cc-connect","slug":"session-resume-timeout","errorCode":null,"errorMessage":"session.resume timeout","messagePattern":"session\\.resume timeout","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"agent/copilot/session.go","lineNumber":186,"sourceCode":"\tcase <-time.After(10 * time.Second):\n\t\treturn fmt.Errorf(\"ping timeout\")\n\tcase <-cs.ctx.Done():\n\t\treturn cs.ctx.Err()\n\t}\n\n\t// Step 2: Create or resume session\n\tif resumeSessionID != \"\" && resumeSessionID != core.ContinueSession {\n\t\t_, resumeCh := cs.rpc.call(\"session.resume\", cs.sessionConfig(resumeSessionID))\n\t\tselect {\n\t\tcase resp := <-resumeCh:\n\t\t\tif resp.Error != nil {\n\t\t\t\tslog.Warn(\"copilotSession: resume failed, creating new session\", \"error\", resp.Error)\n\t\t\t\treturn cs.createSession()\n\t\t\t}\n\t\t\tcs.sessionID.Store(resumeSessionID)\n\t\t\tslog.Info(\"copilotSession: session resumed\", \"sessionId\", resumeSessionID)\n\t\tcase <-time.After(10 * time.Second):\n\t\t\treturn fmt.Errorf(\"session.resume timeout\")\n\t\tcase <-cs.ctx.Done():\n\t\t\treturn cs.ctx.Err()\n\t\t}\n\t} else {\n\t\treturn cs.createSession()\n\t}\n\treturn nil\n}\n\nfunc (cs *copilotSession) createSession() error {\n\t_, createCh := cs.rpc.call(\"session.create\", cs.sessionConfig(newCopilotSessionID()))\n\tselect {\n\tcase resp := <-createCh:\n\t\tif resp.Error != nil {\n\t\t\treturn fmt.Errorf(\"session.create: %w\", resp.Error)\n\t\t}\n\t\tvar result struct {\n\t\t\tSessionID string `json:\"sessionId\"`","sourceCodeStart":168,"sourceCodeEnd":204,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/agent/copilot/session.go#L168-L204","documentation":"During handshake, copilotSession tries to resume a previous Copilot CLI session via a 'session.resume' JSON-RPC call and waits on the response channel for at most 10 seconds. If the CLI process does not answer within that window, the handshake aborts with 'session.resume timeout' instead of blocking forever. The library throws this because an unresponsive child process would otherwise hang the whole agent session startup.","triggerScenarios":"newCopilotSession -> handshake -> cs.rpc.call(\"session.resume\", ...) with a non-empty previous sessionID, and no response arrives on the create/resume channel before time.After(10*time.Second) fires (the CLI is hung, slow to start, or its stdout reader is stalled).","commonSituations":"Copilot CLI binary starting slowly under heavy load or cold start; the previous sessionID in the persisted state is valid but the CLI deadlocks on resume; stdout pipe backpressure because the previous readLoop died; running on a heavily throttled machine (CI container, low-memory host).","solutions":["Retry starting the session — transient slowness is the most common cause; a fresh handshake often resumes in time.","Start a fresh session instead of resuming: clear the stored previous sessionID (e.g. run /new or delete the persisted session state) so handshake falls into createSession().","Check the Copilot CLI process health: confirm the binary launches and responds (cc-connect doctor / run the CLI manually).","Increase the 10s timeout in agent/copilot/session.go if your host is consistently slow to start the CLI.","Inspect copilot CLI logs/stderr for a resume-time deadlock or auth prompt blocking startup."],"exampleFix":"// before: handshake always tries resume with stale ID\nresumeSessionID := cs.prevSessionID\n...\n// after: drop stale session state so a fresh session is created\n// (user action) /new  — or in code, start the agent with an empty sessionID\nopts.SessionID = \"\"","handlingStrategy":"retry","validationCode":"if err := exec.Command(cliPath, \"--version\").Run(); err != nil {\n    return fmt.Errorf(\"copilot CLI not runnable: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"err := agent.StartSession(ctx, opts)\nif err != nil && strings.Contains(err.Error(), \"session.resume timeout\") {\n    // drop stale session and retry fresh\n    opts.SessionID = \"\"\n    err = agent.StartSession(ctx, opts)\n}","preventionTips":["Pre-authenticate the CLI so resume never blocks on interactive input","Clear stale persisted session IDs when switching CLI versions","Retry session start once before reporting failure","Run the CLI manually to confirm it starts within a few seconds on the host"],"tags":["timeout","rpc","session-lifecycle","process-management"],"backgroundTag":"request-timeout","analyzedSha":"4000b2338aa6e850c99df54f8b0ed6ed7460b401","analyzedAt":"2026-09-06T11:45:09.575Z","contentChangedAt":"2026-09-06T11:45:09.575Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}