charmbracelet/crush · error
failed to retire client: %w
Error message
failed to retire client: %w
What it means
RetireClient's generic failure path: the retire-client HTTP request failed (transport error or a non-404 bad status from checkStatus). The underlying cause is wrapped for inspection.
Source
Thrown at internal/client/client.go:197
// RetireClient tells the server this client has exited, releasing every
// claim it holds on every workspace. It is the client's authoritative
// goodbye: after it returns, the server refuses further workspace
// creates from this client ID, so a create whose response was lost cannot
// leave a workspace nobody can name.
//
// Servers predating the endpoint answer 404, reported as
// [ErrUnsupported] so callers can fall back to releasing by workspace ID.
func (c *Client) RetireClient(ctx context.Context) error {
rsp, err := c.delete(ctx, "/clients/"+c.clientID, nil, nil)
if err != nil {
return err
}
defer rsp.Body.Close()
if err := checkStatus(rsp); err != nil {
if errors.Is(err, ErrNotFound) {
return fmt.Errorf("%w: %w", ErrUnsupported, err)
}
return fmt.Errorf("failed to retire client: %w", err)
}
return nil
}
// Dial opens a connection to the server using the same scheme-aware
// logic the client uses for its HTTP transport. Exposed so callers can
// reuse the dialer when they need to construct sibling HTTP transports
// (e.g. a readiness probe in the CLI).
func (c *Client) Dial(ctx context.Context, network, address string) (net.Conn, error) {
return c.dialer(ctx, network, address)
}
func (c *Client) dialer(ctx context.Context, network, address string) (net.Conn, error) {
d := net.Dialer{
Timeout: 30 * time.Second,
KeepAlive: 30 * time.Second,
}
switch c.network {View on GitHub (pinned to 7944b8e522)
Solutions
- Check the wrapped cause for transport vs status failures
- Verify the server process is running and reachable
- Retry the retire call; it is idempotent from the client side
Defensive patterns
Strategy: retry
Validate before calling
// Check server reachability before calling
conn, err := net.DialTimeout("tcp", addr, 2*time.Second)
if err != nil {
return fmt.Errorf("server unreachable: %w", err)
}
conn.Close() Try / catch
if err := c.RetireClient(ctx, id); err != nil {
if ctx.Err() != nil {
return err // canceled; do not retry
}
// retry with backoff
} Prevention
- Use a context with a sane timeout
- Retry idempotent retire calls on transient failures
- Monitor server process health
When it happens
Trigger: Network failure while posting to the retire endpoint; server returns 4xx/5xx other than 404 from checkStatus.
Common situations: Server process died mid-request; connection refused to the server's socket/port; server bug returning 500 on retire.
Understand the failure class
Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.
Related errors
- failed to download from URL: %w
- failed to create request: %w
- failed to fetch URL: %w
- failed to fetch URL: %w
- failed to create request: %w
AI-assisted analysis of charmbracelet/crush@7944b8e522 (2026-08-29).
Data as JSON: /api/errors/005973af6e560d77.
Report an issue: GitHub.