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 workspace

View on GitHub (pinned to 7944b8e522)

Solutions

  1. Restart or reconnect to the crush server and verify it is listening
  2. Retry AgentReadyErr with backoff; treat it as transient connectivity loss
  3. 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

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


AI-assisted analysis of charmbracelet/crush@7944b8e522 (2026-08-29). Data as JSON: /api/errors/32e71f8716ce8143. Report an issue: GitHub.