charmbracelet/crush · error

failed to initialize crush server: %v

Error message

failed to initialize crush server: %v

What it means

replaceExitingServer in internal/cmd/root.go waits for a dying server's unix socket to disappear, then spawns a new server via spawnAndWaitReady. If the new server process fails to start or never reports ready, the error is wrapped as 'failed to initialize crush server: %v'.

Source

Thrown at internal/cmd/root.go:493

		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 server
// version matches the client; on mismatch it shuts down the old server
// and starts a fresh one.
func ensureServer(cmd *cobra.Command, hostURL *url.URL) error {
	// Initialize the persistent log here so stale-socket diagnostics
	// emitted before connectToServer runs are captured in the per-host
	// server log file. crushlog.Setup uses sync.Once internally, so the
	// later call from connectToServer becomes a no-op.
	debug, _ := cmd.Flags().GetBool("debug")
	logFile := filepath.Join(config.GlobalCacheDir(), "server-"+safeHostName(hostURL), "crush.log")
	crushlog.Setup(logFile, debug)

	switch hostURL.Scheme {

View on GitHub (pinned to 7944b8e522)

Solutions

  1. Read the wrapped %v cause and server logs (`crush logs`) for the exact startup failure
  2. Validate crushrc/crush.json — a bad provider/hook line can crash the server at boot
  3. Remove leftover socket files and kill orphan processes, then retry
  4. Ensure the crush binary is up to date and executable on PATH

Example fix

// before
crushrc: hook "bad" { run = "/nonexistent-script" }  # server crashes at startup
// after
# fix or remove the offending hook block, then:
pkill -f 'crush serve'; rm -f ~/.local/share/crush/crush.sock; crush
Defensive patterns

Strategy: fallback

Validate before calling

if err := validateConfig(cfgPath); err != nil {
    return fmt.Errorf("refusing to spawn server with invalid config: %w", err)
}
if fi, err := os.Stat(socketPath); err == nil && fi.Mode()&os.ModeSocket != 0 {
    os.Remove(socketPath)
}

Try / catch

if err := spawnAndWaitReady(ctx, hostURL); err != nil {
    return fmt.Errorf("failed to initialize crush server: %w", err)
}
// fallback: run with a temporary empty config to isolate config vs env issues

Prevention

When it happens

Trigger: spawnAndWaitReady fails: the crush binary/server subcommand errors on startup (port/socket in use, bad config, missing binary on PATH), the ready-signal times out, or the child exits immediately.

Common situations: Broken crushrc config crashing the server at startup; another process bound to the socket/port; permission problems executing the server; crashed server leaving a half-bound socket; timeout on slow machines.

Related errors


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