charmbracelet/crush · error
failed to get sessions: status code %d
Error message
failed to get sessions: status code %d
What it means
ListSessions reached the server but got a non-200 status for GET /workspaces/{id}/sessions. The status code is included in the error. Typical causes: 404 (workspace not found), 401/403 (auth/permissions), 5xx (server error).
Source
Thrown at internal/client/proto.go:666
if rsp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("failed to create session: status code %d", rsp.StatusCode)
}
var sess proto.Session
if err := json.NewDecoder(rsp.Body).Decode(&sess); err != nil {
return nil, fmt.Errorf("failed to decode session: %w", err)
}
return &sess, nil
}
// ListSessions lists all sessions in a workspace as proto types.
func (c *Client) ListSessions(ctx context.Context, id string) ([]proto.Session, error) {
rsp, err := c.get(ctx, fmt.Sprintf("/workspaces/%s/sessions", id), nil, nil)
if err != nil {
return nil, fmt.Errorf("failed to get sessions: %w", err)
}
defer rsp.Body.Close()
if rsp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("failed to get sessions: status code %d", rsp.StatusCode)
}
var sessions []proto.Session
if err := json.NewDecoder(rsp.Body).Decode(&sessions); err != nil {
return nil, fmt.Errorf("failed to decode sessions: %w", err)
}
return sessions, nil
}
// GrantPermission grants a permission on a workspace. The returned
// bool reports whether this call resolved the pending request (true)
// or found it already resolved by a previous caller (false). A false
// value is not an error — it just means another subscriber resolved
// the same request first.
func (c *Client) GrantPermission(ctx context.Context, id string, req proto.PermissionGrant) (bool, error) {
rsp, err := c.post(ctx, fmt.Sprintf("/workspaces/%s/permissions/grant", id), nil, jsonBody(req), http.Header{"Content-Type": []string{"application/json"}})
if err != nil {
return false, fmt.Errorf("failed to grant permission: %w", err)
}View on GitHub (pinned to 7944b8e522)
Solutions
- Branch on the status code from the error message.
- Verify the workspace ID exists.
- Refresh authentication credentials.
- Check permissions for the workspace.
- Retry with backoff on 429/5xx.
Example fix
// before
sessions, err := client.ListSessions(ctx, wsID)
if err != nil { return err }
// after
sessions, err := client.ListSessions(ctx, wsID)
if err != nil {
if strings.Contains(err.Error(), "status code 404") {
return fmt.Errorf("workspace %q not found", wsID)
}
return err
} Defensive patterns
Strategy: try-catch
Validate before calling
// Confirm the workspace exists before listing
_, err := client.GetWorkspace(ctx, wsID)
if err != nil {
return fmt.Errorf("workspace %q not accessible: %w", wsID, err)
} Type guard
func isListStatusError(err error, code int) bool {
return err != nil && strings.Contains(err.Error(), fmt.Sprintf("failed to get sessions: status code %d", code))
} Try / catch
sessions, err := client.ListSessions(ctx, wsID)
if err != nil {
switch {
case isListStatusError(err, 404):
return fmt.Errorf("workspace %q not found", wsID)
case isListStatusError(err, 401), isListStatusError(err, 403):
return fmt.Errorf("auth required: %w", err)
}
return err
} Prevention
- Validate workspace IDs up front.
- Refresh credentials before expiry.
- Check permissions for the workspace.
- Retry only 429/5xx responses.
When it happens
Trigger: Workspace ID does not exist (404); credentials invalid or expired (401/403); server error while enumerating sessions (500); rate limiting (429).
Common situations: Typo in workspace ID; token expired; insufficient permissions on the workspace; server-side outage.
Related errors
- status code %d: %s
- status code %d
- failed to list workspaces: status code %d
- failed to get MCP pending auth: status code %d
- failed to get MCP auth URL: status code %d
AI-assisted analysis of charmbracelet/crush@7944b8e522 (2026-08-29).
Data as JSON: /api/errors/f6ad2c8879ab2b0a.
Report an issue: GitHub.