chenhg5/cc-connect · error

no active session

Error message

no active session

What it means

Before dispatching a 'session.send' RPC, Send reads the current session ID and rejects the call with 'no active session' if it is empty — meaning the JSON-RPC handshake (session.create/session.resume) never completed or the ID was reset. Without a session ID the CLI cannot attach the prompt to a conversation.

Source

Thrown at agent/copilot/session.go:717

	// Handle images: save to temp dir and append file references
	if len(images) > 0 {
		imgPaths, err := saveImagesToTempDir(cs.workDir, images)
		if err != nil {
			slog.Warn("copilotSession: failed to save images", "error", err)
		} else {
			prompt = core.AppendFileRefs(prompt, imgPaths)
		}
	}

	// Handle files
	if len(files) > 0 {
		filePaths := core.SaveFilesToDisk(cs.workDir, messageID, files)
		prompt = core.AppendFileRefs(prompt, filePaths)
	}

	sid := cs.CurrentSessionID()
	if sid == "" {
		return fmt.Errorf("no active session")
	}

	params := map[string]any{
		"sessionId": sid,
		"prompt":    prompt,
	}

	_, sendCh := cs.rpc.call("session.send", params)

	// Don't block - just validate the send was accepted
	go func() {
		select {
		case resp := <-sendCh:
			if resp.Error != nil {
				slog.Error("copilotSession: send failed", "error", resp.Error)
				if cs.alive.Load() {
					evt := core.Event{Type: core.EventError, Error: fmt.Errorf("send: %s", resp.Error.Message)}
					select {

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Retry after the handshake completes — wait for the 'copilotSession: session created/resumed' log line before sending.
  2. Fix the earlier handshake failure: check the CLI is installed, authenticated, and starts within 10s.
  3. Run /new to force a clean session creation, then resend.
  4. Restart cc-connect so handshake runs again from scratch.
  5. If racing during startup, ensure the caller only sends after StartSession returns successfully.

Example fix

// before: send immediately after a failed handshake
sess, _ := agent.StartSession(ctx, opts) // handshake failed, sessionId empty
sess.Send("hi", id, nil, nil)            // "no active session"
// after: check handshake error before using the session
sess, err := agent.StartSession(ctx, opts)
if err != nil {
    return fmt.Errorf("start session: %w", err)
}
sess.Send("hi", id, nil, nil)
Defensive patterns

Strategy: validation

Validate before calling

if session.CurrentSessionID() == "" {
    return fmt.Errorf("session handshake not completed; cannot send")
}

Type guard

func hasActiveSession(s *copilotSession) bool { return s.CurrentSessionID() != "" }

Try / catch

if err := session.Send(prompt, msgID, nil, nil); err != nil && strings.Contains(err.Error(), "no active session") {
    // handshake failed earlier; recreate the session then resend
    session = agent.StartSession(ctx, opts)
    err = session.Send(prompt, msgID, nil, nil)
}

Prevention

When it happens

Trigger: Send is invoked while cs.CurrentSessionID() returns "" — handshake failed or was skipped (e.g. a prior session.resume/create timeout or error left sessionID unset), or the session was recycled without re-running handshake.

Common situations: Startup handshake failed earlier (see 'session.resume timeout' / 'session.create timeout') and the session object was still handed to the engine; session state cleared by /new before the new handshake finished; a race where Send arrives during session setup.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06). Data as JSON: /api/errors/7f4ad7f202fee64a. Report an issue: GitHub.