{"record":{"id":"80f38c5d6f785aab","repo":"Yeachan-Heo/oh-my-codex","slug":"pane-session-mismatch","errorCode":"pane_session_mismatch","errorMessage":"pane_session_mismatch:${tmuxPaneId}:${paneSession || \"missing\"}","messagePattern":"pane_session_mismatch:(.+?):(.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/mcp/hermes-bridge.ts","lineNumber":219,"sourceCode":"  const rawSession = await readSessionState(cwd);\n  if (!rawSession || !sessionMatchesRequested(rawSession, sessionId)) return null;\n  const tmuxSessionName = optionalString(rawSession.tmux_session_name);\n  const tmuxPaneId = optionalString(rawSession.tmux_pane_id);\n  if (!tmuxSessionName || !tmuxPaneId) return null;\n  if (!isTmuxPaneId(tmuxPaneId)) {\n    throw new Error(`unsupported_session_kind:invalid_tmux_pane_binding:${tmuxSessionName}`);\n  }\n\n  const execTmux = deps.execTmuxFileSync ?? defaultExecTmuxFileSync;\n  try {\n    execTmux([\"has-session\", \"-t\", tmuxSessionName]);\n    const instanceId = String(execTmux([\"show-options\", \"-qv\", \"-t\", tmuxSessionName, OMX_INSTANCE_OPTION]) ?? \"\").trim();\n    if (instanceId !== rawSession.session_id) {\n      throw new Error(`tmux_instance_mismatch:${tmuxSessionName}:${instanceId || \"missing\"}`);\n    }\n    const paneSession = String(execTmux([\"display-message\", \"-p\", \"-t\", tmuxPaneId, \"#{session_name}\"]) ?? \"\").trim();\n    if (paneSession !== tmuxSessionName) {\n      throw new Error(`pane_session_mismatch:${tmuxPaneId}:${paneSession || \"missing\"}`);\n    }\n    for (const argv of buildSendPaneArgvs(tmuxPaneId, prompt, true)) {\n      execTmux(argv);\n    }\n  } catch (error) {\n    const message = errorMessage(error);\n    const reason = message.startsWith(\"tmux_instance_mismatch\") || message.startsWith(\"pane_session_mismatch\")\n      ? message\n      : \"tmux_send_failed\";\n    throw new Error(`unsupported_session_kind:tmux_prompt_delivery_failed:${tmuxSessionName}:${tmuxPaneId}:${reason}`);\n  }\n  return {\n    session_id: rawSession.session_id,\n    tmux_session_name: tmuxSessionName,\n    target: tmuxPaneId,\n    transport: \"tmux_send_keys\",\n  };\n}","sourceCodeStart":201,"sourceCodeEnd":237,"githubUrl":"https://github.com/Yeachan-Heo/oh-my-codex/blob/3ad79a8a6fe6e95fdbb8c00e40716fffe4011ce2/src/mcp/hermes-bridge.ts#L201-L237","documentation":"The bridge verifies the bound pane actually belongs to the expected tmux session via display-message #{session_name}. If the pane has moved, died and been recycled, or the id now resolves to another session, this mismatch error is thrown naming the pane and actual session.","triggerScenarios":"execTmux display-message -p -t <paneId> returns a session name different from tmuxSessionName, or empty ('missing') when the pane no longer exists.","commonSituations":"Pane was killed or swapped in tmux (join-pane/move-pane), session was renamed, or a stale state file points at a recycled pane id.","solutions":["Restart the session to rebind to a live pane","Prune session state referencing dead panes","Avoid moving panes between sessions while a bridge binding is active"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":"const paneSession = execSync(`tmux display-message -p -t ${paneId} '#{session_name}'`).toString().trim();\nif (paneSession !== expectedSession) { /* rebind */ }","typeGuard":null,"tryCatchPattern":"catch (e) { if ((e as Error).message.startsWith('pane_session_mismatch')) { /* restart session to obtain fresh pane binding */ } }","preventionTips":["Don't move/kill panes bound to running sessions","Recreate sessions rather than rearranging panes","Check pane liveness before each delivery"],"tags":["mcp","hermes-bridge","tmux","pane-mismatch"],"backgroundTag":"tmux-pane-session-mismatch","analyzedSha":"3ad79a8a6fe6e95fdbb8c00e40716fffe4011ce2","analyzedAt":"2026-08-27T22:18:39.783Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}