slopus/happy · error

Tmux window created but no PID returned

Error message

Tmux window created but no PID returned

What it means

spawnSession launches a session inside a tmux window using tmux -P (print) to capture the spawned process's PID. If tmux reports success but no PID came back, the daemon cannot track the session, so it throws rather than creating an untracked session.

Source

Thrown at packages/happy-cli/src/daemon/run.ts:469

          // Add all safe daemon environment variables (filtering out undefined)
          for (const [key, value] of Object.entries(buildSessionChildEnvironment(ambientEnvironment, extraEnv))) {
            if (value !== undefined) {
              tmuxEnv[key] = value;
            }
          }

          const tmuxResult = await tmux.spawnInTmux([sanitizedTmuxCommand], {
            sessionName: tmuxSessionName,
            windowName: windowName,
            cwd: directory
          }, tmuxEnv);  // Pass complete environment for tmux session

          if (tmuxResult.success) {
            logger.debug(`[DAEMON RUN] Successfully spawned in tmux session: ${tmuxResult.sessionId}, PID: ${tmuxResult.pid}`);

            // Validate we got a PID from tmux
            if (!tmuxResult.pid) {
              throw new Error('Tmux window created but no PID returned');
            }

            // Create a tracked session for tmux windows - now we have the real PID!
            const trackedSession: TrackedSession = {
              startedBy: 'daemon',
              pid: tmuxResult.pid, // Real PID from tmux -P flag
              tmuxSessionId: tmuxResult.sessionId,
              directoryCreated,
              message: directoryCreated
                ? `The path '${directory}' did not exist. We created a new folder and spawned a new session in tmux session '${tmuxSessionName}'. Use 'tmux attach -t ${tmuxSessionName}' to view the session.`
                : `Spawned new session in tmux session '${tmuxSessionName}'. Use 'tmux attach -t ${tmuxSessionName}' to view the session.`
            };

            // Add to tracking map so webhook can find it later
            pidToTrackedSession.set(tmuxResult.pid, trackedSession);

            // Wait for webhook to populate session with happySessionId (exact same as regular flow)
            logger.debug(`[DAEMON RUN] Waiting for session webhook for PID ${tmuxResult.pid} (tmux)`);

View on GitHub (pinned to b824cd0a46)

Solutions

  1. Upgrade tmux to a recent version (≥3.x) so -P returns the pane PID
  2. Run the spawn command manually in tmux to inspect raw -P output
  3. Clear custom tmux configs that change output formats and retry
  4. Restart the daemon and retry spawning the session

Example fix

// before
if (!tmuxResult.pid) {
  throw new Error('Tmux window created but no PID returned');
}
// after
if (!tmuxResult.pid) {
  logger.warn('tmux returned no PID; falling back to pgrep lookup');
  tmuxResult.pid = findPidBySessionId(tmuxResult.sessionId);
}
if (!tmuxResult.pid) {
  throw new Error('Tmux window created but no PID returned');
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Before spawning, verify tmux supports -P PID output
class CheckTmux {
  static async version() {
    const out = spawn.sync('tmux', ['-V']).stdout?.toString() || '';
    return out; // expect tmux 3.x
  }
}

Try / catch

try {
  const session = await spawnSession(opts);
} catch (err) {
  if (err.message === 'Tmux window created but no PID returned') {
    console.error('Upgrade tmux (>=3.x) or clear custom tmux output-format configs, then retry.');
  } else throw err;
}

Prevention

When it happens

Trigger: tmuxResult.success is true but tmuxResult.pid is falsy — the tmux -P output was empty or unparsed, e.g. an older tmux version or unexpected output format.

Common situations: tmux installed via an old version that doesn't print the pane PID as expected; tmux config (hooks, alternate formats) alters -P output; session spawning inside a wrapper that swallows tmux output.

Related errors


AI-assisted analysis of slopus/happy@b824cd0a46 (2026-08-31). Data as JSON: /api/errors/583cd5e5b632d945. Report an issue: GitHub.