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

restored_hud_cleanup_debt_unresolved:${debt.pane_id}

Error message

restored_hud_cleanup_debt_unresolved:${debt.pane_id}

What it means

While replaying a persisted 'HUD cleanup debt' (a HUD pane that had to be killed on shutdown but could not be verified then), the recorded HUD pane is proven live with the right PID but the debt record lacks a leader_pane_owner_id — so authorization for the kill cannot be established and the debt is left unresolved (fail-closed).

Source

Thrown at src/team/tmux-session.ts:534

  syncRestoredHudDebtParentSync(path);
}

/**
 * Replays a prior restored-HUD obligation. A live pane is killable only when
 * its recorded PID, HUD command identity, and tagged leader identity all
 * still match; PID-less and ambiguous records remain durable debt.
 */
export function reconcileRestoredHudCleanupDebtSync(cwd: string, stateRoot?: string | null): void {
  const record = parseRestoredHudCleanupDebtSync(cwd, stateRoot);
  if (!record) return;
  const { path, debt } = record;
  const proof = readExactPaneProofSync(debt.pane_id);
  if (proof.status === 'gone') {
    removeRestoredHudCleanupDebtSync(path);
    return;
  }
  if (proof.status !== 'live' || debt.pane_pid === null || proof.pid !== debt.pane_pid || !debt.leader_pane_owner_id) {
    throw new Error(`restored_hud_cleanup_debt_unresolved:${debt.pane_id}`);
  }
  const leader = requireLiveTeamOwnedPaneSync(debt.leader_pane_id, debt.leader_pane_pid, debt.leader_pane_owner_id);
  const topology = listPanesResult(leader);
  const hudMatches = !topology.error && topology.panes.filter((pane) => pane.paneId === proof.paneId
    && hudPaneMatchesOwner(pane, { leaderPaneId: debt.hud_owner_leader_pane_id })).length === 1;
  if (!hudMatches) throw new Error(`restored_hud_cleanup_debt_unresolved:${debt.pane_id}`);
  killExactPaneSync(proof.paneId, debt.pane_pid, () => {
    requireLiveTeamOwnedPaneSync(debt.leader_pane_id, debt.leader_pane_pid, debt.leader_pane_owner_id!);
  });
  removeRestoredHudCleanupDebtSync(path);
}

/** Remove restored-HUD debt only after the canonical config transaction commits the same frozen identity. */
export function finalizeRestoredHudCleanupDebtSync(
  cwd: string,
  paneId: string,
  panePid: number,
  stateRoot?: string | null,

View on GitHub (pinned to 3ad79a8a6f)

Solutions

  1. Inspect the debt record under the team state root and manually kill the leftover HUD pane (`tmux kill-pane -t <pane_id>`) once verified
  2. Delete the stale debt record only after confirming the HUD pane is gone
  3. Regenerate the session state by recreating the team session
Defensive patterns

Strategy: fallback

Validate before calling

const debt = readDebt(stateRoot); if (debt && !debt.leader_pane_owner_id) flagForManualCleanup(debt.pane_id);

Try / catch

catch (e) { if (/restored_hud_cleanup_debt_unresolved/.test(e.message)) { queueManualCleanup(e.message.split(':').pop()); return; } throw e; }

Prevention

When it happens

Trigger: Restoring a team session whose persisted cleanup-debt JSON has leader_pane_owner_id missing/null (old format or truncated write), while the HUD pane still exists and matches its recorded PID.

Common situations: Upgrading between versions that changed the debt record schema; state file corrupted by a crash mid-write; leftover debt from an experimentally modified session.

Related errors


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