charmbracelet/crush · error

failed to start crush server: %v

Error message

failed to start crush server: %v

What it means

Wraps the error returned by exec.Cmd.Start() when launching a detached Crush server child process. It means the OS refused to spawn the configured binary - typically the executable path does not exist, is not executable, or the working directory is invalid. The wrap preserves the underlying errno (e.g. 'no such file or directory').

Source

Thrown at internal/cmd/root.go:895

	stderrPath := filepath.Join(chDir, "stderr.log")
	detachProcess(c)

	stdout, err := os.Create(stdoutPath)
	if err != nil {
		return fmt.Errorf("failed to create stdout log file: %v", err)
	}
	defer stdout.Close()
	c.Stdout = stdout

	stderr, err := os.Create(stderrPath)
	if err != nil {
		return fmt.Errorf("failed to create stderr log file: %v", err)
	}
	defer stderr.Close()
	c.Stderr = stderr

	if err := c.Start(); err != nil {
		return fmt.Errorf("failed to start crush server: %v", err)
	}

	if err := c.Process.Release(); err != nil {
		return fmt.Errorf("failed to detach crush server process: %v", err)
	}

	return nil
}

func shouldEnableMetrics(cfg *config.Config) bool {
	if v, _ := strconv.ParseBool(os.Getenv("CRUSH_DISABLE_METRICS")); v {
		return false
	}
	if v, _ := strconv.ParseBool(os.Getenv("DO_NOT_TRACK")); v {
		return false
	}
	if cfg.Options.DisableMetrics {
		return false

View on GitHub (pinned to 7944b8e522)

Solutions

  1. Verify the crush binary exists and is executable: `which crush && test -x $(which crush)`
  2. Check that PATH in the spawning environment includes the binary's directory
  3. Run the command manually to see the underlying errno from the wrapped message
  4. Reinstall or update crush if the binary was removed by an upgrade

Example fix

// before: binary resolved from an env-var-derived path that may be empty
exe := os.Getenv("CRUSH_BIN")
c := exec.Command(exe, "serve")
// after: resolve explicitly and fail early
exe, err := exec.LookPath("crush")
if err != nil {
	return fmt.Errorf("crush binary not found in PATH: %w", err)
}
c := exec.Command(exe, "serve")
Defensive patterns

Strategy: validation

Validate before calling

exe, err := exec.LookPath("crush")
if err != nil {
	return fmt.Errorf("crush binary not found: %w", err)
}
if info, err := os.Stat(exe); err != nil || info.IsDir() || info.Mode()&0o111 == 0 {
	return fmt.Errorf("crush binary missing or not executable: %s", exe)
}

Try / catch

if err := startDetachedServer(cmd); err != nil {
	var execErr *exec.Error
	if errors.As(err, &execErr) {
		slog.Error("Server binary not found; check PATH/install", "bin", execErr.Name)
	}
	return err
}

Prevention

When it happens

Trigger: Calling spawnAndWaitReady -> startDetachedServer where exec.Command points at a non-existent or non-executable binary, the command's Dir is missing, or resource limits (fork failures) prevent process creation.

Common situations: Crush installed outside PATH; PATH stripped in systemd/launchd/cron environments; stale binary after an upgrade or uninstall; minimal containers without the binary.

Related errors


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