Yeachan-Heo/oh-my-codex · error · Error

startup_cleanup_pane_owner_unavailable:${cleanupPane.pane_id

Error message

startup_cleanup_pane_owner_unavailable:${cleanupPane.pane_id}:${owner.error}

What it means

To prove ownership of a cleanup pane the code reads the pane's team-owner tmux tag; if that read itself errors (tmux command failure, missing user option, shell error), the check cannot distinguish 'ours' from 'not ours', so it aborts with the pane id and the underlying error string.

Source

Thrown at src/team/runtime.ts:409

    }
    const proof = readExactPaneProofSync(cleanupPane.pane_id);
    if (proof.status === 'gone') {
      resolvedPaneIds.add(cleanupPane.pane_id);
      continue;
    }
    if (proof.status === 'unavailable') {
      assertPaneTeardownProofsAvailable('startup_cleanup', [proof]);
      continue;
    }
    if (cleanupPane.pid === null) {
      throw new Error(`startup_cleanup_pane_pid_missing:${cleanupPane.pane_id}`);
    }
    if (proof.pid !== cleanupPane.pid) {
      throw new Error(`startup_cleanup_pane_identity_changed:${cleanupPane.pane_id}`);
    }
    const owner = readPaneTeamOwnerTagResult(cleanupPane.pane_id);
    if (owner.status === 'error') {
      throw new Error(`startup_cleanup_pane_owner_unavailable:${cleanupPane.pane_id}:${owner.error}`);
    }
    if (owner.status !== 'value' || owner.value !== teamPaneOwnerId) {
      throw new Error(`startup_cleanup_pane_owner_changed:${cleanupPane.pane_id}`);
    }
    expectedPanePids[cleanupPane.pane_id] = cleanupPane.pid;
  }

  const livePaneIds = Object.keys(expectedPanePids);
  if (livePaneIds.length > 0) {
    const teardown = await teardownWorkerPanes(livePaneIds, {
      leaderPaneId: config.leader_pane_id,
      hudPaneId: config.hud_pane_id,
      expectedPanePids,
      authorizePaneKill: (paneId, proof) => {
        if (expectedPanePids[paneId] !== proof.pid) return false;
        const owner = readPaneTeamOwnerTagResult(paneId);
        return owner.status === 'value' && owner.value === teamPaneOwnerId;
      },

View on GitHub (pinned to 3ad79a8a6f)

Solutions

  1. Verify tmux is running and the pane's session still exists (`tmux has-session` / `tmux list-panes`)
  2. Retry the reconcile — transient tmux server races often clear
  3. Check the appended owner.error string for the concrete tmux failure (exit code / stderr)
Defensive patterns

Strategy: retry

Try / catch

try { await reconcileStartupCleanupPanes(config, cwd); } catch (e) { if (e instanceof Error && e.message.startsWith('startup_cleanup_pane_owner_unavailable:') && e.message.includes(':')) { const err = e.message.split(':').pop(); /* inspect tmux error; retry on transient */ } throw e; }

Prevention

When it happens

Trigger: readPaneTeamOwnerTagResult returning status 'error' — tmux not installed/not running, session destroyed mid-read, `tmux show-options -p` failing, or a malformed user option.

Common situations: tmux server restarted or exited between existence check and tag read; SSH session drop; PATH issues finding tmux in the runtime environment.

Related errors


AI-assisted analysis of Yeachan-Heo/oh-my-codex@3ad79a8a6f (2026-08-27). Data as JSON: /api/errors/e601e23c2a8eefb0. Report an issue: GitHub.