chenhg5/cc-connect · critical

pi: start rpc: %w

Error message

pi: start rpc: %w

What it means

newPiSession starts pi's RPC subprocess; s.startRPC(resumeID) handles spawning the `pi` binary and wiring pipes. Any failure inside startRPC (binary not found, exec failure, pipe setup, cmd.Start error) is wrapped as 'pi: start rpc'. This is the generic wrapper for 'the pi RPC process could not be launched'.

Source

Thrown at agent/pi/session.go:147

		rpc:       rpc,
		extraEnv:  extraEnv,
		attachDir: filepath.Join(workDir, ".cc-connect", "attachments", fmt.Sprintf("pi_%d", time.Now().UnixNano())),
		events:    make(chan core.Event, 64),
		ctx:       ctx,
		cancel:    cancel,
		modelsCW:  loadModelsContextWindows(),
	}
	s.alive.Store(true)

	if rpc {
		s.rpcReady = make(chan struct{})
		s.extPending = make(map[string]string)
		s.extPendingRev = make(map[string]string)
		s.extMethod = make(map[string]string)

		if err := s.startRPC(resumeID); err != nil {
			cancel()
			return nil, fmt.Errorf("pi: start rpc: %w", err)
		}

		// Wait for first JSON line (indicates RPC loop is live)
		select {
		case <-s.rpcReady:
		case <-time.After(30 * time.Second):
			s.killRPC()
			cancel()
			return nil, fmt.Errorf("pi: rpc process did not become ready within 30s")
		case <-ctx.Done():
			s.killRPC()
			return nil, fmt.Errorf("pi: context cancelled while waiting for rpc ready")
		}
	} else if resumeID != "" && resumeID != core.ContinueSession {
		// JSON mode: set the session ID directly since we don't spawn a process
		// that would emit a session event.
		s.sessionID.Store(resumeID)
	}

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Run `which pi` (or the configured binary) as the SAME user that runs cc-connect to confirm it's on PATH.
  2. Set an absolute path for the pi binary in the agent's cliPath config option instead of relying on PATH.
  3. Install/upgrade the pi CLI (`npm i -g @mariozechner/pi` or the package's install command) and verify `pi --version` works.
  4. Check the wrapped cause with errors.Is(err, exec.ErrNotFound) to distinguish missing binary from other start failures.

Example fix

// before (config.toml)
[agents.pi]
cliPath = "pi"
// after (config.toml)
[agents.pi]
cliPath = "/usr/local/bin/pi"
Defensive patterns

Strategy: validation

Validate before calling

bin := cliPath // or "pi"
if p, err := exec.LookPath(bin); err != nil {
    return fmt.Errorf("pi binary %q not found on PATH for user %q: %w", bin, os.Getenv("USER"), err)
}

Try / catch

sess, err := agent.StartSession(ctx, opts)
if err != nil {
    if errors.Is(err, exec.ErrNotFound) {
        return fmt.Errorf("pi CLI is not installed or not on PATH; install it or set cliPath: %w", err)
    }
    return fmt.Errorf("start pi session: %w", err)
}

Prevention

When it happens

Trigger: Calling StartSession (or Resume) in RPC mode when: the pi binary is not on PATH (exec not found), the configured CLI path is wrong, the binary lacks execute permission, or cmd.Start fails for OS reasons (fork/resource limits).

Common situations: pi CLI not installed or installed under a different name/version; PATH inside the cc-connect daemon differs from the interactive shell PATH (systemd scrubbed PATH); wrong cliPath in config.toml after pi upgrade or rename.

Related errors


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