{"record":{"id":"096ad61e84b32cee","repo":"Yeachan-Heo/oh-my-codex","slug":"shutdown-config-missing-after-detached-reconciliat","errorCode":null,"errorMessage":"shutdown_config_missing_after_detached_reconciliation:${sanitized}","messagePattern":"shutdown_config_missing_after_detached_reconciliation:(.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"critical","filePath":"src/team/runtime.ts","lineNumber":4872,"sourceCode":"  let skipWorkerAcks = false;\n  const sanitized = resolveTeamNameForCurrentContext(teamName, cwd);\n  let config = await readTeamConfig(sanitized, cwd);\n  if (!config) {\n    await reconcileDetachedSessionDestroyReceipt(sanitized, cwd, null);\n    await reconcileGonePaneDescendantCleanupDebt(sanitized, cwd);\n    // A missing config is not authority over a conventionally named tmux\n    // session. It may be another team's or a recycled user session.\n    await cleanupTeamState(sanitized, cwd);\n    await syncTeamModeStateOnShutdown(sanitized, cwd);\n    restoreTeamModelInstructionsFile(sanitized);\n    return { commitHygieneArtifacts: null };\n  }\n  // Reconcile accepted detached-session destruction before any other shutdown\n  // effect. A receipt is the only durable authority across the kill/query crash\n  // window and is deliberately fail-closed on malformed or unavailable input.\n  await reconcileDetachedSessionDestroyReceipt(sanitized, cwd, config);\n  config = await readTeamConfig(sanitized, cwd);\n  if (!config) throw new Error(`shutdown_config_missing_after_detached_reconciliation:${sanitized}`);\n  config = await reconcileStartupCleanupPanes(config, cwd);\n  const restoredHudDebtRoot = join(config.team_state_root ?? resolveCanonicalTeamStateRoot(cwd), 'team', sanitized);\n  const configuredRestoredHudPaneId = typeof config.hud_pane_id === 'string' && /^%[0-9]+$/.test(config.hud_pane_id)\n    ? config.hud_pane_id\n    : null;\n  const configuredRestoredHudPanePid = typeof config.hud_pane_pid === 'number'\n    && Number.isSafeInteger(config.hud_pane_pid)\n    && config.hud_pane_pid > 0\n    ? config.hud_pane_pid\n    : null;\n  if (configuredRestoredHudPaneId && configuredRestoredHudPanePid) {\n    try {\n      // A restored-HUD debt is finalized only when this canonical config\n      // transaction records its exact frozen pane identity. A stale config may\n      // point to a different HUD after a crash, so replay the pinned debt\n      // rather than treating that mismatch as successful finalization.\n      finalizeRestoredHudCleanupDebtSync(\n        cwd,","sourceCodeStart":4854,"sourceCodeEnd":4890,"githubUrl":"https://github.com/Yeachan-Heo/oh-my-codex/blob/3ad79a8a6fe6e95fdbb8c00e40716fffe4011ce2/src/team/runtime.ts#L4854-L4890","documentation":"Fail-closed guard in team shutdown: after reconciling detached-session destroy receipts, the team config can no longer be read. The shutdown deliberately aborts rather than proceed without authoritative config, naming the team in the message.","triggerScenarios":"Shutting down a team whose config disappears or becomes unreadable specifically after reconcileDetachedSessionDestroyReceipt runs — e.g. the reconciliation itself removed/renamed the state, or an external process deleted the config concurrently.","commonSituations":"Concurrent shutdown invocations racing on the same team; external cleanup scripts deleting team state mid-shutdown; corrupted config file that readTeamConfig cannot parse (returns null).","solutions":["Check whether another shutdown already completed and removed the team config; if so, treat shutdown as done","Restore or recreate the team config, then re-run shutdown","Serialize shutdowns per team (lock) and stop external deletions of team state during shutdown"],"exampleFix":"// before\nawait shutdownTeam(team, cwd);\n\n// after\nconst config = await readTeamConfig(team, cwd);\nif (!config) { /* already gone */ return; }\nawait withTeamShutdownLock(team, () => shutdownTeam(team, cwd));","handlingStrategy":"fallback","validationCode":"const config = await readTeamConfig(teamName, cwd);\nif (!config) return; // already shut down","typeGuard":null,"tryCatchPattern":"try { await shutdownTeam(t, cwd); } catch (e) { if (/^shutdown_config_missing_after_detached_reconciliation:/.test((e as Error).message)) return; /* idempotent */ throw e; }","preventionTips":["Make shutdown idempotent; tolerate already-deleted configs","Serialize shutdown per team","Prevent external deletions of team state during shutdown"],"tags":["shutdown","config","race-condition"],"backgroundTag":"missing-config-during-shutdown","analyzedSha":"3ad79a8a6fe6e95fdbb8c00e40716fffe4011ce2","analyzedAt":"2026-08-27T22:18:39.783Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}