chenhg5/cc-connect · error

another cc-connect instance is already running (PID %d) with

Error message

another cc-connect instance is already running (PID %d) with config %s

What it means

AcquireInstanceLock takes an exclusive non-blocking flock; when it is already held, the lock file is parsed for a PID and this error reports the PID of the running instance plus the config path. It is an intentional, expected error meaning a second cc-connect instance is attempting to use the same config concurrently.

Source

Thrown at cmd/cc-connect/instance_lock.go:55

		return nil, fmt.Errorf("cannot create config directory: %w", err)
	}

	// Open/create the lock file
	f, err := os.OpenFile(lockPath, os.O_CREATE|os.O_RDWR, 0644)
	if err != nil {
		return nil, fmt.Errorf("cannot open lock file: %w", err)
	}

	// Try to acquire exclusive lock (non-blocking)
	err = syscall.Flock(int(f.Fd()), syscall.LOCK_EX|syscall.LOCK_NB)
	if err != nil {
		// Lock is held by another process
		f.Close()

		// Try to read PID from lock file for better error message
		pid := readPIDFromLockFile(lockPath)
		if pid > 0 {
			return nil, fmt.Errorf("another cc-connect instance is already running (PID %d) with config %s", pid, configPath)
		}
		return nil, fmt.Errorf("another cc-connect instance is already running with config %s", configPath)
	}

	// Write our PID to the lock file for diagnostics
	pid := os.Getpid()
	_ = f.Truncate(0)
	_, _ = f.Seek(0, 0)
	fmt.Fprintf(f, "%d\n", pid)

	return &InstanceLock{
		file:     f,
		path:     lockPath,
		acquired: true,
	}, nil
}

// Release releases the instance lock. It is safe to call multiple times.

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Verify the running instance: ps -p <PID> and stop it if unwanted (kill <PID> or systemctl stop cc-connect).
  2. If you truly want a second instance, use a different --config path so a different lock file is used.
  3. If PID is stale (process gone), remove the lock file and retry — flock is released automatically when the holder dies.

Example fix

// shell
// before
cc-connect --config ~/.config/cc-connect/config.toml
// after
systemctl --user stop cc-connect && cc-connect --config ~/.config/cc-connect/config.toml
Defensive patterns

Strategy: try-catch

Try / catch

lock, err := AcquireInstanceLock(configPath)
if err != nil {
    var pid int
    if _, scanErr := fmt.Sscanf(err.Error(), "another cc-connect instance is already running (PID %d)", &pid); scanErr == nil {
        fmt.Fprintf(os.Stderr, "instance %d already running; stopping.\n", pid)
    }
    os.Exit(1)
}

Prevention

When it happens

Trigger: Calling AcquireInstanceLock(configPath) while another live cc-connect process holds LOCK_EX on <configDir>/.<configBase>.lock and its PID was successfully read from the lock file.

Common situations: Starting a second daemon manually while a systemd/launchd service is running; a duplicated terminal run; a stale process that is actually still alive despite the user thinking it stopped.

Related errors


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