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
- Start (or restart) the Fresh editor for that session, then retry the command.
- Verify the session id: `echo $FRESH_SESSION` inside the workspace shell, or list running fresh processes.
- Remove stale socket state for the dead session if it blocks a new launch.
- 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
- Confirm the editor is alive before scripted command bursts.
- Generate session ids once and store them alongside the editor process lifecycle.
- Clean up dead-session sockets to avoid stale references.
- Prefer reading $FRESH_SESSION from the live workspace shell over hardcoded ids.
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
- not inside a Fresh session; set --session
- handshake with the Fresh editor failed
- server error
- server closed the connection before answering
- Server error
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)