sinelaw/fresh · error

no running Fresh editor for session

Error message

no running Fresh editor for session '{}'

What it means

resolve_cmd_socket probes the session's control socket; when liveness is Dead (socket exists but no live editor answers / editor has exited), it bails that no running Fresh editor exists for the session id. This distinguishes an exited editor from an unreachable (permission-blocked) socket.

Solutions

  1. Start (or restart) the Fresh editor for that session, then retry the command.
  2. Verify the session id: `echo $FRESH_SESSION` inside the workspace shell, or list running fresh processes.
  3. Remove stale socket state for the dead session if it blocks a new launch.
  4. If you intended a live session but got this, check whether the sandbox is masking the socket (that case yields the socket-denied message instead).

Example fix

// before (editor already closed)
fresh --session old-session --cmd quit
// after
fresh --session old-session main.rs   # restart editor first, then send commands
Defensive patterns

Strategy: retry

Validate before calling

// probe liveness before sending commands
const { execSync } = require('child_process');
try { execSync(`pgrep -f 'fresh.*${session}'`, { stdio: 'ignore' }); }
catch { console.error(`No running editor for session ${session}; start it first`); process.exit(1); }

Try / catch

// bash
if ! fresh --session "$S" --cmd ping 2>/dev/null; then
  echo "editor for $S is down; restarting..."
  fresh --session "$S" . || exit 1
fi

Prevention

When it happens

Trigger: `fresh --session <id> --cmd ...` (or script run) where the editor that owned the session has terminated but the session id/socket is still referenced.

Common situations: Editor crashed or was closed between commands; stale scripts/aliases referencing an old session id; re-running a command from a saved history after the editor session ended; wrong session id that matches nothing running.

Understand the failure class

Background: ECONNREFUSED and "connection refused" / "could not connect to server" errors: what they mean and how to fix them — this error's family across 44 libraries.

Related errors


AI-assisted analysis of sinelaw/fresh@67894ca546 (2026-09-13). Data as JSON: /api/errors/384aeb49ee4dd0b7. Report an issue: GitHub.

Appendix: source

Thrown at crates/fresh-editor/src/main.rs:3564

            Ok(s) if !s.trim().is_empty() => s,
            _ => anyhow::bail!(
                "not inside a Fresh session; set --session <id> (or run inside a \
                 Fresh workspace so $FRESH_SESSION is set)"
            ),
        },
    };

    let socket_paths = resolve_session(Some(&session))?;
    socket_paths.cleanup_if_stale();
    match socket_paths.probe_server() {
        ServerLiveness::Alive => Ok(socket_paths),
        // Denied rather than absent. Say so, and say what to do: a caller that
        // can re-run outside its sandbox (an agent with an escalation path)
        // can act on this, whereas "no running editor" sends it hunting for a
        // stale session that is in fact alive and well.
        ServerLiveness::Unreachable => Err(socket_denied_error(&session, &socket_paths)),
        ServerLiveness::Dead => {
            anyhow::bail!("no running Fresh editor for session '{}'", session)
        }
    }
}

/// How long a command-channel client waits for the editor to answer before
/// giving up.
///
/// The default suits a command that answers within a frame — a query, a split,
/// a dispatch. A command that *does* something slow before it can answer (a
/// workspace create runs `git worktree add` and waits for the agent process to
/// come up) passes its own, longer bound. Either way an explicit
/// `FRESH_CMD_TIMEOUT_MS` wins, so a caller can always widen the wait without
/// the CLI having to guess.
fn cmd_reply_timeout_or(default: std::time::Duration) -> std::time::Duration {
    std::env::var("FRESH_CMD_TIMEOUT_MS")
        .ok()
        .and_then(|v| v.trim().parse::<u64>().ok())
        .filter(|ms| *ms > 0)

View on GitHub (pinned to 67894ca546)