chenhg5/cc-connect · error

tmux: create session

Error message

tmux: create session %q: %w

What it means

When the tmux session is missing and auto_create is enabled, StartSession calls createTmuxSession and wraps any underlying failure with 'tmux: create session %q: %w'. This is the intermediate wrap around the raw tmux exec error (errorIndex 350), preserving both the session name and tmux's own output.

Solutions

  1. Read the wrapped inner error for tmux's message
  2. Create the work_dir or fix the work_dir value in config
  3. Fix or remove the shell option if it names a missing binary
  4. Create the session manually with tmux new-session -d -s <name> and disable auto_create

Example fix

// before
[agents.options]
session = "cc"
auto_create = true
work_dir = "/srv/app" # does not exist

// after
mkdir -p /srv/app
# or point work_dir at an existing path
work_dir = "/home/user/app"
Defensive patterns

Strategy: validation

Validate before calling

if _, err := os.Stat(workDir); err != nil { return fmt.Errorf("auto_create work_dir missing: %w", err) }
if shell != "" { if _, err := exec.LookPath(shell); err != nil { return err } }

Try / catch

if _, err := agent.StartSession(ctx, opts); err != nil {
    var inner error
    if errors.Unwrap(errors.Unwrap(err)) != nil { inner = errors.Unwrap(errors.Unwrap(err)) }
    slog.Error("tmux auto-create failed", "session", sessionName, "cause", inner)
    return err
}

Prevention

When it happens

Trigger: auto_create = true, session does not exist, and `tmux new-session` fails: nonexistent work_dir (-c), invalid shell, or tmux server error creating the session.

Common situations: work_dir pointing to a directory that does not exist yet (e.g. project not cloned); shell option naming an uninstalled binary; concurrent auto-create of the same session name by two agents.

Related errors


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

Appendix: source

Thrown at agent/tmux/tmux.go:181

	//     isolation; each gets its own init_command/agent instance).
	//   - else, when workDir is a real path: a window named after the directory
	//     so each workspace gets its own instance.
	//   - else: the legacy session:pane target.
	// windowForSession may allocate a fresh window name when sessionID is empty;
	// the returned ID is persisted by the engine so resumes reuse the same window.
	windowName, effectiveSessionID := a.windowForSession(sessionName, pane, workDir, sessionID)
	sessionID = effectiveSessionID
	target := sessionName + ":" + windowName

	sessionExists := tmuxSessionExists(sessionName)
	windowExists := sessionExists && tmuxWindowExists(target)

	if !sessionExists {
		if !autoCreate {
			return nil, fmt.Errorf("tmux: session %q does not exist and auto_create is disabled", sessionName)
		}
		if err := createTmuxSession(sessionName, windowName, workDir, shell); err != nil {
			return nil, fmt.Errorf("tmux: create session %q: %w", sessionName, err)
		}
		slog.Info("tmux: created session", "session", sessionName, "window", windowName, "work_dir", workDir)
	} else if !windowExists && windowName != pane {
		// Session exists but this workspace window does not yet — create it.
		if err := createTmuxWindow(sessionName, windowName, workDir); err != nil {
			return nil, fmt.Errorf("tmux: create window %q in session %q: %w", windowName, sessionName, err)
		}
		slog.Info("tmux: created window", "session", sessionName, "window", windowName, "work_dir", workDir)
	}

	newPane := !sessionExists || (!windowExists && windowName != pane)
	if newPane {
		// Always cd to the workspace directory so the shell (and any init_command)
		// starts in the right place, regardless of tmux's -c flag behaviour.
		if workDir != "" && workDir != "." {
			if err := sendKeys(target, "cd "+shellQuote(workDir)); err != nil {
				slog.Warn("tmux: cd failed", "work_dir", workDir, "err", err)
			}

View on GitHub (pinned to 4000b2338a)