charmbracelet/crush · error
failed to get workspace: %w
Error message
failed to get workspace: %w
What it means
GetWorkspace wraps an error returned by the client's underlying c.get transport call (building/sending the HTTP GET /workspaces/{id}). This fires before any status checking, so it indicates the request itself failed at the network/transport layer, not that the server rejected it. The original error (e.g. connection refused, context canceled) is preserved via %w.
Source
Thrown at internal/client/proto.go:62
if err != nil {
return nil, fmt.Errorf("failed to create workspace: %w", err)
}
defer rsp.Body.Close()
if err := checkStatus(rsp); err != nil {
return nil, fmt.Errorf("failed to create workspace: %w", err)
}
var created proto.Workspace
if err := json.NewDecoder(rsp.Body).Decode(&created); err != nil {
return nil, fmt.Errorf("failed to decode workspace: %w", err)
}
return &created, nil
}
// GetWorkspace retrieves a workspace from the server.
func (c *Client) GetWorkspace(ctx context.Context, id string) (*proto.Workspace, error) {
rsp, err := c.get(ctx, fmt.Sprintf("/workspaces/%s", id), nil, nil)
if err != nil {
return nil, fmt.Errorf("failed to get workspace: %w", err)
}
defer rsp.Body.Close()
if err := checkStatus(rsp); err != nil {
return nil, fmt.Errorf("failed to get workspace: %w", err)
}
var ws proto.Workspace
if err := json.NewDecoder(rsp.Body).Decode(&ws); err != nil {
return nil, fmt.Errorf("failed to decode workspace: %w", err)
}
return &ws, nil
}
// DeleteWorkspace deletes a workspace on the server.
func (c *Client) DeleteWorkspace(ctx context.Context, id string) error {
q := url.Values{"client_id": []string{c.clientID}}
rsp, err := c.delete(ctx, fmt.Sprintf("/workspaces/%s", id), q, nil)
if err != nil {
return fmt.Errorf("failed to delete workspace: %w", err)View on GitHub (pinned to 7944b8e522)
Solutions
- Confirm the crush server is running and reachable (curl the /workspaces endpoint).
- Check the client's configured server URL/port matches the server's actual listen address.
- Use errors.Is(err, context.DeadlineExceeded) to distinguish timeout vs connectivity and retry with a longer deadline.
- Retry the request; transient network errors often resolve.
- Verify DNS resolution and any proxy environment variables (HTTP_PROXY/HTTPS_PROXY) are correct.
Example fix
// before
ws, err := client.GetWorkspace(ctx, id)
if err != nil { return err }
// after: classify and retry transport errors
ws, err := client.GetWorkspace(ctx, id)
if err != nil {
if errors.Is(err, context.DeadlineExceeded) || errors.Is(err, context.Canceled) {
return err
}
time.Sleep(time.Second)
ws, err = client.GetWorkspace(ctx, id)
if err != nil { return fmt.Errorf("get workspace: %w", err) }
} Defensive patterns
Strategy: retry
Validate before calling
// probe reachability before the call
conn, err := net.DialTimeout("tcp", host, 2*time.Second)
if err != nil { return fmt.Errorf("server unreachable: %w", err) }
conn.Close() Try / catch
ws, err := client.GetWorkspace(ctx, id)
if err != nil {
if errors.Is(err, context.Canceled) || errors.Is(err, context.DeadlineExceeded) {
return err
}
var ne net.Error
if errors.As(err, &ne) && ne.Timeout() {
return retryWithBackoff()
}
return err
} Prevention
- Health-check the server before workspace operations.
- Use generous but bounded context deadlines.
- Centralize retry/backoff for all client calls.
- Keep server address in one validated config value.
When it happens
Trigger: Calling client.GetWorkspace(ctx, id) when the crush server is unreachable: wrong URL/port, server process down, TLS handshake failure, or the passed context is canceled/expired mid-request.
Common situations: crush serve not running or crashed; client configured with a stale or mistyped server address; firewall/network partition; a long-running operation whose context deadline exceeded before the GET completed.
Related errors
- failed to delete workspace: %w
- failed to make request: %w
- failed to refresh OAuth token: %w
- failed to check project init: %w
- failed to mark project initialized: %w
AI-assisted analysis of charmbracelet/crush@7944b8e522 (2026-08-29).
Data as JSON: /api/errors/fca23244f82a389b.
Report an issue: GitHub.