{"record":{"id":"355d2292ccbe371a","repo":"Yeachan-Heo/oh-my-codex","slug":"startup-cleanup-pane-owner-unavailable-missing-tea","errorCode":null,"errorMessage":"startup_cleanup_pane_owner_unavailable:missing_team_owner_id","messagePattern":"startup_cleanup_pane_owner_unavailable:missing_team_owner_id","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/team/runtime.ts","lineNumber":384,"sourceCode":"          startup_cleanup_panes: current.startup_cleanup_panes,\n        }, null, 2),\n      },\n    });\n    const committed = await readTeamConfig(current.name, cwd);\n    if (!committed) throw new Error(`shutdown_config_missing_after_commit:${current.name}`);\n    return committed;\n  });\n}\n\nexport async function reconcileStartupCleanupPanes(\n  config: TeamConfig,\n  cwd: string,\n): Promise<TeamConfig> {\n  const cleanupPanes = config.startup_cleanup_panes ?? [];\n  if (cleanupPanes.length === 0) return config;\n\n  const teamPaneOwnerId = config.tmux_pane_owner_id?.trim() ?? '';\n  if (!teamPaneOwnerId) throw new Error('startup_cleanup_pane_owner_unavailable:missing_team_owner_id');\n\n  const resolvedPaneIds = new Set<string>();\n  const expectedPanePids: Record<string, number> = {};\n  for (const cleanupPane of cleanupPanes) {\n    if (cleanupPane.pane_id === config.leader_pane_id || cleanupPane.pane_id === config.hud_pane_id) {\n      throw new Error(`startup_cleanup_pane_target_invalid:${cleanupPane.pane_id}`);\n    }\n    const proof = readExactPaneProofSync(cleanupPane.pane_id);\n    if (proof.status === 'gone') {\n      resolvedPaneIds.add(cleanupPane.pane_id);\n      continue;\n    }\n    if (proof.status === 'unavailable') {\n      assertPaneTeardownProofsAvailable('startup_cleanup', [proof]);\n      continue;\n    }\n    if (cleanupPane.pid === null) {\n      throw new Error(`startup_cleanup_pane_pid_missing:${cleanupPane.pane_id}`);","sourceCodeStart":366,"sourceCodeEnd":402,"githubUrl":"https://github.com/Yeachan-Heo/oh-my-codex/blob/3ad79a8a6fe6e95fdbb8c00e40716fffe4011ce2/src/team/runtime.ts#L366-L402","documentation":"reconcileStartupCleanupPanes must kill leftover startup panes via tmux, and to do that safely it needs the team's pane-owner tag ID (tmux_pane_owner_id) to verify ownership. If cleanup panes are configured but that owner id is missing/blank, there is no way to prove the panes belong to this team, so it refuses rather than risk killing foreign panes.","triggerScenarios":"A config with non-empty startup_cleanup_panes but tmux_pane_owner_id unset, empty, or whitespace — typically hand-edited or migrated configs predating the owner-tag feature.","commonSituations":"Configs created by an older version before tmux_pane_owner_id existed; manual config.json edits stripping the field; tests with minimal fixture configs.","solutions":["Restore/set tmux_pane_owner_id in the team config (a non-empty unique owner tag)","Clear startup_cleanup_panes if the panes are already gone and no owner proof is needed","Recreate the team with the current version so the config is fully populated"],"exampleFix":"// before\n{ startup_cleanup_panes: [{pane_id: '%5', pid: 123}] }\n// after\n{ tmux_pane_owner_id: 'omx-team-myteam-ab12', startup_cleanup_panes: [{pane_id: '%5', pid: 123}] }","handlingStrategy":"validation","validationCode":"if ((config.startup_cleanup_panes?.length ?? 0) > 0 && !(config.tmux_pane_owner_id?.trim())) {\n  config.startup_cleanup_panes = undefined; // or fail with a clear message\n}","typeGuard":null,"tryCatchPattern":"try { await reconcileStartupCleanupPanes(config, cwd); } catch (e) { if (e instanceof Error && e.message === 'startup_cleanup_pane_owner_unavailable:missing_team_owner_id') { /* populate owner id or clear cleanup panes */ } throw e; }","preventionTips":["Never hand-edit startup_cleanup_panes without tmux_pane_owner_id","Migrate legacy configs by restarting the team"],"tags":["team-runtime","tmux","pane-ownership","config-validation"],"backgroundTag":"ownership-proof-missing","analyzedSha":"3ad79a8a6fe6e95fdbb8c00e40716fffe4011ce2","analyzedAt":"2026-08-27T22:18:39.783Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}