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

  1. Branch on the status code from the error message.
  2. Verify the workspace ID exists.
  3. Refresh authentication credentials.
  4. Check permissions for the workspace.
  5. 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

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


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