{"record":{"id":"8a3700ab2d88e3d2","repo":"chenhg5/cc-connect","slug":"pi-start-rpc-w","errorCode":null,"errorMessage":"pi: start rpc: %w","messagePattern":"pi: start rpc: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"agent/pi/session.go","lineNumber":147,"sourceCode":"\t\trpc:       rpc,\n\t\textraEnv:  extraEnv,\n\t\tattachDir: filepath.Join(workDir, \".cc-connect\", \"attachments\", fmt.Sprintf(\"pi_%d\", time.Now().UnixNano())),\n\t\tevents:    make(chan core.Event, 64),\n\t\tctx:       ctx,\n\t\tcancel:    cancel,\n\t\tmodelsCW:  loadModelsContextWindows(),\n\t}\n\ts.alive.Store(true)\n\n\tif rpc {\n\t\ts.rpcReady = make(chan struct{})\n\t\ts.extPending = make(map[string]string)\n\t\ts.extPendingRev = make(map[string]string)\n\t\ts.extMethod = make(map[string]string)\n\n\t\tif err := s.startRPC(resumeID); err != nil {\n\t\t\tcancel()\n\t\t\treturn nil, fmt.Errorf(\"pi: start rpc: %w\", err)\n\t\t}\n\n\t\t// Wait for first JSON line (indicates RPC loop is live)\n\t\tselect {\n\t\tcase <-s.rpcReady:\n\t\tcase <-time.After(30 * time.Second):\n\t\t\ts.killRPC()\n\t\t\tcancel()\n\t\t\treturn nil, fmt.Errorf(\"pi: rpc process did not become ready within 30s\")\n\t\tcase <-ctx.Done():\n\t\t\ts.killRPC()\n\t\t\treturn nil, fmt.Errorf(\"pi: context cancelled while waiting for rpc ready\")\n\t\t}\n\t} else if resumeID != \"\" && resumeID != core.ContinueSession {\n\t\t// JSON mode: set the session ID directly since we don't spawn a process\n\t\t// that would emit a session event.\n\t\ts.sessionID.Store(resumeID)\n\t}","sourceCodeStart":129,"sourceCodeEnd":165,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/agent/pi/session.go#L129-L165","documentation":"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'.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Run `which pi` (or the configured binary) as the SAME user that runs cc-connect to confirm it's on PATH.","Set an absolute path for the pi binary in the agent's cliPath config option instead of relying on PATH.","Install/upgrade the pi CLI (`npm i -g @mariozechner/pi` or the package's install command) and verify `pi --version` works.","Check the wrapped cause with errors.Is(err, exec.ErrNotFound) to distinguish missing binary from other start failures."],"exampleFix":"// before (config.toml)\n[agents.pi]\ncliPath = \"pi\"\n// after (config.toml)\n[agents.pi]\ncliPath = \"/usr/local/bin/pi\"","handlingStrategy":"validation","validationCode":"bin := cliPath // or \"pi\"\nif p, err := exec.LookPath(bin); err != nil {\n    return fmt.Errorf(\"pi binary %q not found on PATH for user %q: %w\", bin, os.Getenv(\"USER\"), err)\n}","typeGuard":null,"tryCatchPattern":"sess, err := agent.StartSession(ctx, opts)\nif err != nil {\n    if errors.Is(err, exec.ErrNotFound) {\n        return fmt.Errorf(\"pi CLI is not installed or not on PATH; install it or set cliPath: %w\", err)\n    }\n    return fmt.Errorf(\"start pi session: %w\", err)\n}","preventionTips":["Pin an absolute cliPath in config.toml instead of relying on daemon PATH.","Run `cc-connect doctor` (or `which pi` as the service user) at deploy time.","Re-verify the binary path after every pi upgrade or rename."],"tags":["go","process-spawn","rpc","exec"],"backgroundTag":"command-not-found","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"}