Hmbown/CodeWhale · error
tmux has-session for
Error message
tmux has-session for {session} failed with {}: {} What it means
`tmux_session_state` runs `tmux has-session -t <session>` against a pinned socket to classify whether a lane's tmux session is Present or Absent. Known-benign stderr patterns ("can't find session:", "no server running on", "error connecting to" + "no such file or directory") are treated as Absent; any other nonzero exit means tmux failed in an unexpected way, so the runtime bails rather than guessing the session state. Callers `stop_tmux_session` and `reconcile` depend on this classification being trustworthy, which is why failure is loud.
Solutions
- Run `tmux -S <socket> has-session -t <session>` manually to see the full stderr and diagnose the actual tmux failure.
- If the tmux server protocol is stale (version mismatch), kill the old server (`tmux -S <socket> kill-server`) or remove the stale socket file, then retry the stop/reconcile.
- Check socket permissions/ownership — ensure the runtime process runs as the same user that created the session.
- If the session is genuinely gone but tmux errors oddly, remove the lane record or clear its pinned tmux_socket/tmux_session metadata so reconcile treats it as absent.
Example fix
// diagnose $ tmux -S /run/codewhale/lane.sock has-session -t lane-42 # error connecting to /run/codewhale/lane.sock: Permission denied $ sudo rm /run/codewhale/lane.sock # stale socket owned by another user
Defensive patterns
Strategy: try-catch
Validate before calling
let out = std::process::Command::new("tmux")
.args(["-S", socket, "has-session", "-t", session])
.output()
.map_err(|e| e.to_string())?;
if !out.status.success() && !is_benign_absence(&String::from_utf8_lossy(&out.stderr)) {
return Err(String::from_utf8_lossy(&out.stderr).into());
} Prevention
- Use a dedicated socket directory owned by the runtime user.
- Kill stale tmux servers after tmux version upgrades.
- Don't share lane sockets across user accounts.
When it happens
Trigger: Calling `stop` or `reconcile` on a tmux lane when `tmux has-session` exits nonzero with stderr that matches none of the benign absence patterns — e.g. the socket path is stale/unreachable, tmux reports a protocol-version mismatch with an existing server, the socket file has wrong permissions, or tmux is corrupted.
Common situations: A tmux server was upgraded between runs so the on-disk socket speaks an incompatible protocol; the pinned socket path was deleted or recreated with different permissions; a stale socket directory with a dead server that tmux cannot clean up; running the runtime as a different user who cannot access the socket.
Related errors
- tmux new-session failed with
- tmux session remains active after kill-session ( )
- Cannot resolve current binary path
- Cloud agent harness exited with code
- exited
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/594676a8a309487b.
Report an issue: GitHub.
Appendix: source
Thrown at crates/lane/src/runtime.rs:588
fn tmux_session_state(socket: &Path, session: &str) -> Result<TmuxSessionState> {
let output = tmux_command(socket)
.args(["has-session", "-t", session])
.stdout(Stdio::null())
.stderr(Stdio::piped())
.output()
.with_context(|| format!("query tmux session {session}"))?;
if output.status.success() {
return Ok(TmuxSessionState::Present);
}
let stderr = String::from_utf8_lossy(&output.stderr).to_ascii_lowercase();
if stderr.contains("can't find session:")
|| stderr.contains("no server running on")
|| (stderr.contains("error connecting to") && stderr.contains("no such file or directory"))
{
return Ok(TmuxSessionState::Absent);
}
bail!(
"tmux has-session for {session} failed with {}: {}",
output.status,
stderr.trim()
)
}
fn stop_tmux_session(socket: &Path, session: &str) -> Result<()> {
let status = tmux_command(socket)
.args(["kill-session", "-t", session])
.stdout(Stdio::null())
.stderr(Stdio::null())
.status()
.with_context(|| format!("kill tmux session {session}"))?;
match tmux_session_state(socket, session).with_context(|| {
format!(
"confirm tmux session {session} on {} stopped after kill-session ({status})",
socket.display()
)View on GitHub (pinned to 73e0f67d83)