affaan-m/ECC · error · Error
tmux session already exists
Error message
tmux session already exists: ${plan.sessionName} What it means
executePlan refuses to start when a tmux session with plan.sessionName already exists (checked via 'tmux has-session -t'). This prevents attaching duplicate panes/workers into an existing session or silently reusing stale state from a previous run.
Solutions
- Kill the existing session: run 'tmux kill-session -t <sessionName>' and re-run the orchestrator.
- Use a different sessionName in the plan if the old session must be preserved.
- Attach to the existing session ('tmux attach -t <sessionName>') if it is actually the run you want.
- Check for and clean up leftover sessions after crashed runs: 'tmux ls'.
Example fix
// before (fails) node orchestrator.js --session my-session // after tmux kill-session -t my-session node orchestrator.js --session my-session
Defensive patterns
Strategy: validation
Validate before calling
const { status } = spawnSync('tmux', ['has-session', '-t', sessionName], { stdio: 'ignore' });
if (status === 0) {
console.error(`session '${sessionName}' exists — kill it first: tmux kill-session -t ${sessionName}`);
process.exit(1);
} Try / catch
try {
executePlan(plan);
} catch (err) {
if (String(err.message).startsWith('tmux session already exists')) {
spawnSync('tmux', ['kill-session', '-t', plan.sessionName], { stdio: 'inherit' });
executePlan(plan); // retry once after cleanup
return;
}
throw err;
} Prevention
- Run 'tmux ls' before starting and kill stale sessions from crashed runs
- Use unique session names per user/task to avoid team collisions
- Wrap orchestration in a script that kills the session in a trap/finally block
- Only reuse a session name intentionally after confirming the old run is dead
When it happens
Trigger: Calling executePlan twice with the same sessionName; a previous run crashed after creating the tmux session but before cleanup; skipExistingSession/precheck flag disabled so the has-session check runs and returns status 0.
Common situations: Re-running the orchestrator after an aborted run without cleanup; two team members launching the same session name concurrently; session left over from an interactive tmux experiment with the same name.
Related errors
- buildOrchestrationPlan requires at least one worker
- Cannot delete active session
- Cannot merge active session
- Cannot rebase active session
- Canonical session snapshot requires
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/988a709475ab759e.
Report an issue: GitHub.
Appendix: source
Thrown at scripts/lib/tmux-worktree-orchestrator.js:506
const rollbackCreatedResourcesImpl = runtime.rollbackCreatedResources || rollbackCreatedResources;
const createdState = {
workerPlans: [],
sessionCreated: false,
removeCoordinationDir: !fs.existsSync(plan.coordinationDir)
};
runCommandImpl('git', ['rev-parse', '--is-inside-work-tree'], { cwd: plan.repoRoot });
runCommandImpl('tmux', ['-V']);
if (plan.replaceExisting) {
cleanupExistingImpl(plan);
} else {
const hasSession = spawnSyncImpl('tmux', ['has-session', '-t', plan.sessionName], {
encoding: 'utf8',
stdio: ['ignore', 'pipe', 'pipe']
});
if (hasSession.status === 0) {
throw new Error(`tmux session already exists: ${plan.sessionName}`);
}
}
try {
materializePlanImpl(plan);
for (const workerPlan of plan.workerPlans) {
runCommandImpl('git', workerPlan.gitArgs, { cwd: plan.repoRoot });
createdState.workerPlans.push(workerPlan);
overlaySeedPathsImpl({
repoRoot: plan.repoRoot,
seedPaths: workerPlan.seedPaths,
worktreePath: workerPlan.worktreePath
});
}
runCommandImpl(
'tmux',View on GitHub (pinned to 8321021c54)