charmbracelet/crush · error
failed to create workspace: server kept shutting down
Error message
failed to create workspace: server kept shutting down
What it means
createWorkspaceOnLiveServer in internal/cmd/root.go gives up after maxStaleServerRetries attempts when every failure is client.ErrServerShuttingDown, returning the fixed message 'failed to create workspace: server kept shutting down'. It means a dying server kept being hit and even replacement attempts did not yield a healthy server.
Source
Thrown at internal/cmd/root.go:481
// instead of failing the command.
func createWorkspaceOnLiveServer(
ctx context.Context, c *client.Client, req proto.Workspace, replace func() error,
) (*proto.Workspace, error) {
for attempt := range maxStaleServerRetries {
ws, err := c.CreateWorkspace(ctx, req)
if err == nil {
return ws, nil
}
if !errors.Is(err, client.ErrServerShuttingDown) || attempt == maxStaleServerRetries-1 {
return nil, fmt.Errorf("failed to create workspace: %v", err)
}
slog.Warn("Server is shutting down; retrying against a replacement",
"attempt", attempt+1, "error", err)
if err := replace(); err != nil {
return nil, err
}
}
return nil, fmt.Errorf("failed to create workspace: server kept shutting down")
}
// replaceExitingServer waits out the socket of a server that has committed
// to exiting, then brings up a fresh one.
func replaceExitingServer(cmd *cobra.Command, hostURL *url.URL) error {
if hostURL.Scheme == "unix" {
if err := awaitSocketGone(cmd.Context(), hostURL); err != nil {
return err
}
}
if err := spawnAndWaitReady(cmd, hostURL); err != nil {
return fmt.Errorf("failed to initialize crush server: %v", err)
}
return nil
}
// ensureServer auto-starts a detached server if the socket file does not
// exist. When the socket exists, it verifies that the running serverView on GitHub (pinned to 7944b8e522)
Solutions
- Find and kill all crush server processes: pgrep -af crush; pkill -f 'crush serve'
- Remove the stale socket file and retry so a fresh server spawns
- Disable or fix the supervisor (systemd unit / docker restart policy) that keeps cycling the server
- Reboot or wait for system shutdown to complete before retrying
Example fix
// shell, before crush # keeps hitting a cycling server // after pkill -f 'crush serve'; rm -f ~/.local/share/crush/crush.sock crush
Defensive patterns
Strategy: retry
Validate before calling
if running, err := serverIsRunning(sock); err == nil && !running {
os.Remove(sock) // clear stale socket before connecting
} Try / catch
ws, err := createWorkspaceOnLiveServer(cmd, req, replace)
if err != nil {
if strings.Contains(err.Error(), "server kept shutting down") {
pkill -f 'crush serve'; os.Remove(sock); // then retry from a clean state
}
return err
} Prevention
- Kill stale servers and remove stale socket files before connecting
- Disable conflicting restart supervisors for the same socket
- Investigate why the server keeps exiting (check `crush logs`)
When it happens
Trigger: Every CreateWorkspace call across all retries returned ErrServerShuttingDown — e.g. multiple stale servers in a shutdown loop, or a supervisor (systemd/docker) continuously restarting/terminating the server on the same socket.
Common situations: Container orchestrator repeatedly restarting the crush server; multiple crush processes racing on one unix socket; system shutdown in progress; socket file lingering while its server exits.
Related errors
- failed to create workspace: %v
- not found
- server is shutting down
- failed to initialize crush server: %v
- client not attached
AI-assisted analysis of charmbracelet/crush@7944b8e522 (2026-08-29).
Data as JSON: /api/errors/72c0d0879de55a98.
Report an issue: GitHub.