Hmbown/CodeWhale · error · anyhow::Error

running tmux lane `{}` lacks pinned socket/session metadata;

Error message

running tmux lane `{}` lacks pinned socket/session metadata; refusing unsafe reconciliation

What it means

During reconciliation of a Running tmux lane with no exit receipt on disk, the runtime must query the pinned tmux session — but the record lacks tmux_socket/tmux_session (and CODEWHALE_LANE_TMUX_DRY_RUN is unset, which would short-circuit). It bails rather than guessing, so a metadata-less Running lane surfaces loudly instead of being silently misclassified.

Source

Thrown at crates/lane/src/runtime.rs:905

        let (lane_status, exit_code, reason) = if let Some(receipt) = receipt {
            (
                if receipt.exit_code == 0 {
                    LaneStatus::Completed
                } else {
                    LaneStatus::Failed
                },
                Some(receipt.exit_code),
                "process_exit_receipt",
            )
        } else {
            if std::env::var_os("CODEWHALE_LANE_TMUX_DRY_RUN").is_some() {
                return Ok(false);
            }
            let (Some(socket), Some(session)) = (
                record.tmux_socket.as_deref(),
                record.tmux_session.as_deref(),
            ) else {
                bail!(
                    "running tmux lane `{}` lacks pinned socket/session metadata; refusing unsafe reconciliation",
                    record.id
                );
            };
            match tmux_session_state(socket, session)? {
                TmuxSessionState::Present => return Ok(false),
                TmuxSessionState::Absent => {}
            }
            (
                LaneStatus::Failed,
                None,
                "tmux_session_missing_without_exit_receipt",
            )
        };

        if registry.mark_terminal_if_active(record, lane_status)? {
            append_log_event(
                &record.log_path,

View on GitHub (pinned to 0c42157ee5)

Solutions

  1. Determine the lane's actual tmux session manually and repair the record's tmux_socket/tmux_session, then reconcile again
  2. If the session is gone, kill leftovers and transition the lane to a terminal state through supported APIs
  3. Prevent recurrence: always start tmux lanes via the current runtime so metadata is pinned at creation
Defensive patterns

Strategy: validation

Validate before calling

fn lane_reconcilable(record: &LaneRecord) -> bool {
    record.status != LaneStatus::Running
        || record.tmux_socket.is_some() && record.tmux_session.is_some()
}

Type guard

fn lane_has_pinned_session(record: &LaneRecord) -> bool {
    record.tmux_socket.is_some() && record.tmux_session.is_some()
}

Prevention

When it happens

Trigger: Reconciliation (status refresh/recovery after a crash) hitting a Running lane record whose tmux_socket or tmux_session is None. Same root causes as the stop-side refusal: legacy records, edited state, partial migrations.

Common situations: Restarting the parent process after an upgrade while old Running lanes exist in the registry; restoring a registry from backup; tools that create Running records without going through TmuxRuntime::start.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@0c42157ee5 (2026-08-20). Data as JSON: /api/errors/0aff0d2c5a7808ec. Report an issue: GitHub.