charmbracelet/crush · error · ErrServerUnreachable
lost connection to the crush server
Error message
lost connection to the crush server
What it means
ErrServerUnreachable is a sentinel error meaning the client could not reach the crush server to determine the agent's status — either the server is down or the workspace was torn down out from under the client. It is returned by AgentReadyErr so callers can distinguish connectivity loss from an uninitialized agent.
Source
Thrown at internal/workspace/workspace.go:38
"github.com/charmbracelet/crush/internal/oauth"
"github.com/charmbracelet/crush/internal/permission"
"github.com/charmbracelet/crush/internal/proto"
"github.com/charmbracelet/crush/internal/question"
"github.com/charmbracelet/crush/internal/session"
"github.com/charmbracelet/crush/internal/skills"
)
// Reasons the coder agent may be unavailable, returned by
// Workspace.AgentReadyErr so callers can tell a genuinely
// uninitialized agent apart from a lost server connection.
var (
// ErrAgentNotInitialized means the workspace exists but its coder
// agent has not been configured/initialized (e.g. no model set).
ErrAgentNotInitialized = errors.New("coder agent is not initialized")
// ErrServerUnreachable means the client could not reach the server
// to determine the agent's status (server down, or the workspace was
// torn down out from under the client).
ErrServerUnreachable = errors.New("lost connection to the crush server")
// ErrWorkspaceGone means the server is reachable but no longer knows
// this client's workspace: it was torn down, or the server was
// replaced underneath the client. The subscription loop re-registers
// the workspace in the background when it sees this.
ErrWorkspaceGone = errors.New("the server reset this workspace; reconnecting")
// ErrStreamClosed means an established event stream ended.
// Resubscribing usually succeeds immediately, but events published in
// the meantime are lost for good, so the client treats it as a
// degraded link that requires a resync.
ErrStreamClosed = errors.New("the event stream closed; reconnecting")
)
// ConnectionState describes the health of the client-server link as
// reported by the [ClientWorkspace] subscription loop.
type ConnectionState int
const (
// ConnectionDegraded means the event stream is down (or the workspaceView on GitHub (pinned to 7944b8e522)
Solutions
- Restart or reconnect to the crush server and verify it is listening
- Retry AgentReadyErr with backoff; treat it as transient connectivity loss
- Re-create the workspace/client if the server was permanently replaced
Defensive patterns
Strategy: retry
Validate before calling
// probe before use
if err := ws.AgentReadyErr(ctx); errors.Is(err, workspace.ErrServerUnreachable) {
// defer or queue the request
} Type guard
func isServerUnreachable(err error) bool { return errors.Is(err, workspace.ErrServerUnreachable) } Try / catch
if err != nil {
if errors.Is(err, workspace.ErrServerUnreachable) {
return retryWithBackoff(ctx, op)
}
return err
} Prevention
- Run the crush server under a supervisor (systemd) so it auto-restarts
- Use exponential backoff for AgentReadyErr/SendMessage retries
- Monitor server liveness from the client before batching work
When it happens
Trigger: AgentReadyErr called while the server process is down or restarting; the workspace the client holds was torn down server-side so status queries fail at the transport level.
Common situations: Server crashed or was killed mid-session; network drop between client and server; server redeploy removed the workspace the client cached.
Related errors
- empty providers list from catwalk
- github copilot not available
- question cancelled by user
- coder agent is not initialized
- failed to make request: %w
AI-assisted analysis of charmbracelet/crush@7944b8e522 (2026-08-29).
Data as JSON: /api/errors/32e71f8716ce8143.
Report an issue: GitHub.