charmbracelet/crush · warning

unsupported by the running server

Error message

unsupported by the running server

What it means

ErrUnsupported in internal/client/errors.go is a sentinel returned when the running crush server predates an RPC/feature the client is trying to use. Unlike transient failures, it signals a protocol/feature-version mismatch: the server understood the connection but not this specific request. Callers (e.g. ShutdownServerIfIdle, RetireClient, restartIfStale) wrap it so older-server situations can be distinguished from network or availability errors.

Source

Thrown at internal/client/errors.go:36

	ErrNotFound = errors.New("not found")

	// ErrServerBusy reports that the server declined to shut down
	// because it is still hosting workspaces or is midway through
	// creating one. A client asking a version-mismatched server to stand
	// down must keep using it instead of assuming it is going away.
	ErrServerBusy = errors.New("server busy")

	// ErrServerShuttingDown reports that the server refused the request
	// because it has already committed to exiting. The work is not lost:
	// a replacement server can be started and the request retried
	// against it.
	ErrServerShuttingDown = errors.New("server is shutting down")

	// ErrUnsupported reports that the running server does not understand
	// the request because it predates the feature. Callers must decide
	// what is safe to do with an older server rather than treating the
	// failure as transient.
	ErrUnsupported = errors.New("unsupported by the running server")
)

// checkStatus returns nil when rsp's status code is one of ok
// (http.StatusOK when none are given). Otherwise it returns an error
// carrying the status code and, when the body decodes as a proto.Error,
// the server-provided message. Statuses that callers act on are wrapped
// in the matching sentinel. checkStatus may consume the response body.
func checkStatus(rsp *http.Response, ok ...int) error {
	if len(ok) == 0 {
		ok = []int{http.StatusOK}
	}
	if slices.Contains(ok, rsp.StatusCode) {
		return nil
	}
	var err error
	if msg := decodeErrorMessage(rsp.Body); msg != "" {
		err = fmt.Errorf("status code %d: %s", rsp.StatusCode, msg)
	} else {

View on GitHub (pinned to 7944b8e522)

Solutions

  1. Restart or upgrade the running crush server so client and server versions match.
  2. Check the error with errors.Is(err, client.ErrUnsupported) and take a safe fallback for older servers (e.g. skip graceful shutdown, just kill the process).
  3. Ensure no stale server process is left over (pkill old crush daemon) before starting the new client.

Example fix

// before
if err := client.ShutdownServerIfIdle(ctx); err != nil {
    return err
}
// after
if err := client.ShutdownServerIfIdle(ctx); err != nil {
    if errors.Is(err, client.ErrUnsupported) {
        // Old server: safe to proceed without graceful shutdown.
        return nil
    }
    return err
}
Defensive patterns

Strategy: type-guard

Validate before calling

// Compare client and server versions before calling feature-specific RPCs
if clientVersion != serverVersion {
    log.Println("version mismatch possible: some RPCs may be unsupported")
}

Type guard

func isUnsupported(err error) bool { return errors.Is(err, client.ErrUnsupported) }

Try / catch

if err := c.ShutdownServerIfIdle(ctx); err != nil {
    if isUnsupported(err) {
        // older server: take safe fallback
        return nil
    }
    return err
}

Prevention

When it happens

Trigger: Calling client.ShutdownServerIfIdle or client.RetireClient against a server binary older than the feature; restartIfStale attempting the shutdown RPC on a stale server that lacks it; any request that checkStatus maps to the unsupported sentinel.

Common situations: Mixed-version setups: a newly installed crush client talking to a long-running server daemon started by an older version; skipping an upgrade so background server processes keep the old build alive; CI environments with cached old server binaries.

Related errors


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