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
- Restart or upgrade the running crush server so client and server versions match.
- 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).
- 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
- Keep client and server binaries on the same version; restart stale daemons after upgrading.
- Always use errors.Is against ErrUnsupported instead of string matching.
- Design callers with explicit older-server fallbacks rather than treating the error as transient.
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
- clipboard operations are not supported on this platform
- clipboard is empty or holds an unsupported format
- Crush crashed. If metrics are enabled, we were notified abou
- empty providers list from catwalk
- file lock is held by another process
AI-assisted analysis of charmbracelet/crush@7944b8e522 (2026-08-29).
Data as JSON: /api/errors/13d9f51360b7e45c.
Report an issue: GitHub.