affaan-m/ECC · error · Error

tmux split-window did not return a pane id for

Error message

tmux split-window did not return a pane id for ${workerPlan.workerName}

What it means

executePlan creates one tmux pane per worker via 'tmux split-window -d -P -F #{pane_id}' and relies on tmux echoing the new pane id on stdout. If the command succeeds but returns an empty string, the pane id cannot be targeted by later select-pane/send-keys calls, so it throws for that worker.

Solutions

  1. Check your tmux version ('tmux -V'); upgrade to a modern tmux (>= 2.x) that reliably supports 'split-window -P -F #{pane_id}'.
  2. Run the split command manually to see what it prints: tmux split-window -d -P -F '#{pane_id}' -t <session>.
  3. If you pass a custom runtime.runCommand, verify it returns stdout from spawnSync (encoding: 'utf8') rather than discarding it.
  4. Retry the run — a transient tmux server failure can produce an empty pane id.

Example fix

// before (old tmux without -P support)
tmux split-window -d -t my-session
tmux list-panes -F '#{pane_id}' -t my-session | tail -1
// after (tmux >= 2.1)
paneId=$(tmux split-window -d -P -F '#{pane_id}' -t my-session)
Defensive patterns

Strategy: try-catch

Validate before calling

const tmuxV = spawnSync('tmux', ['-V'], { encoding: 'utf8' }).stdout.trim();
const [ , major ] = tmuxV.match(/tmux (\d+)/) || [];
if (!major || Number(major) < 2) {
  throw new Error(`tmux ${tmuxV} lacks reliable split-window -P support; upgrade tmux`);
}

Type guard

const hasPaneId = (out) => typeof out === 'string' && /^%\d+$/.test(out.trim());

Try / catch

const paneId = splitResult.stdout.trim();
if (!paneId) {
  console.error('tmux returned no pane id; tmux version:', spawnSync('tmux', ['-V'], { encoding: 'utf8' }).stdout.trim());
  // fall back: list panes and diff before/after
}

Prevention

When it happens

Trigger: tmux split-window exits 0 but prints nothing — typically a tmux version quirk with -P/-F, output being swallowed (stdio redirection issue in runCommandImpl), or a session that terminated between split and read; also when the spawn wrapper captures stdout but tmux writes the pane id to a different format target.

Common situations: Very old tmux versions without full -P/-F support; a custom runCommandImpl in the runtime override that drops stdout; the tmux server dying mid-run; race where the session closes immediately after split.

Related errors


AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16). Data as JSON: /api/errors/aadf84ed2cd584cc. Report an issue: GitHub.

Appendix: source

Thrown at scripts/lib/tmux-worktree-orchestrator.js:550

        'send-keys',
        '-t',
        plan.sessionName,
        buildSessionBannerCommand(plan.sessionName, plan.coordinationDir),
        'C-m'
      ],
      { cwd: plan.repoRoot }
    );

    for (const workerPlan of plan.workerPlans) {
      const splitResult = runCommandImpl(
        'tmux',
        ['split-window', '-d', '-P', '-F', '#{pane_id}', '-t', plan.sessionName, '-c', workerPlan.worktreePath],
        { cwd: plan.repoRoot }
      );
      const paneId = splitResult.stdout.trim();

      if (!paneId) {
        throw new Error(`tmux split-window did not return a pane id for ${workerPlan.workerName}`);
      }

      runCommandImpl('tmux', ['select-layout', '-t', plan.sessionName, 'tiled'], { cwd: plan.repoRoot });
      runCommandImpl('tmux', ['select-pane', '-t', paneId, '-T', workerPlan.workerSlug], {
        cwd: plan.repoRoot
      });
      runCommandImpl(
        'tmux',
        [
          'send-keys',
          '-t',
          paneId,
          `cd ${shellQuote(workerPlan.worktreePath)} && ${workerPlan.launchCommand}`,
          'C-m'
        ],
        { cwd: plan.repoRoot }
      );
    }

View on GitHub (pinned to 8321021c54)