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

shutdown_config_missing_after_commit:${current.name}

Error message

shutdown_config_missing_after_commit:${current.name}

What it means

After mutateShutdownConfig writes the updated config it re-reads it to return the committed version; if that read comes back null, the config that was just written cannot be found — a self-inconsistency indicating the write and read disagree (race with deletion, fs sync issue, or state root mismatch). Distinct from 867: the config existed at the start but vanished after commit.

Source

Thrown at src/team/runtime.ts:371

    const currentManifest = currentManifestBytes === null ? null : JSON.parse(currentManifestBytes) as Record<string, unknown>;
    await commitTeamMembershipTaskTransaction(current.name, cwd, {
      baseGeneration,
      tasks: [],
      config: { oldBytes: currentConfigBytes, newBytes: JSON.stringify(current, null, 2) },
      manifest: {
        oldBytes: currentManifestBytes,
        newBytes: currentManifest === null ? null : JSON.stringify({
          ...currentManifest,
          hud_pane_id: current.hud_pane_id,
          hud_pane_pid: current.hud_pane_pid,
          resize_hook_name: current.resize_hook_name,
          resize_hook_target: current.resize_hook_target,
          startup_cleanup_panes: current.startup_cleanup_panes,
        }, null, 2),
      },
    });
    const committed = await readTeamConfig(current.name, cwd);
    if (!committed) throw new Error(`shutdown_config_missing_after_commit:${current.name}`);
    return committed;
  });
}

export async function reconcileStartupCleanupPanes(
  config: TeamConfig,
  cwd: string,
): Promise<TeamConfig> {
  const cleanupPanes = config.startup_cleanup_panes ?? [];
  if (cleanupPanes.length === 0) return config;

  const teamPaneOwnerId = config.tmux_pane_owner_id?.trim() ?? '';
  if (!teamPaneOwnerId) throw new Error('startup_cleanup_pane_owner_unavailable:missing_team_owner_id');

  const resolvedPaneIds = new Set<string>();
  const expectedPanePids: Record<string, number> = {};
  for (const cleanupPane of cleanupPanes) {
    if (cleanupPane.pane_id === config.leader_pane_id || cleanupPane.pane_id === config.hud_pane_id) {

View on GitHub (pinned to 3ad79a8a6f)

Solutions

  1. Retry the shutdown after confirming with `omx team status` that state is consistent
  2. Serialize shutdowns per team (the barrier should ensure this — check for barrier bypass)
  3. Check disk space and permissions on the team state root
Defensive patterns

Strategy: retry

Try / catch

try { await mutateShutdownConfig(...); } catch (e) { if (e instanceof Error && e.message.startsWith('shutdown_config_missing_after_commit:')) { await delay(500); return mutateShutdownConfig(...); /* one retry */ } throw e; }

Prevention

When it happens

Trigger: Another process deletes or renames the team state directory between the write and the re-read; or the write silently failed (disk full, permissions) while reporting success.

Common situations: Two concurrent shutdown commands for the same team, container filesystems with delayed visibility, or state-root symlinks changing mid-operation.

Related errors


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