charmbracelet/crush · error

failed to get MCP pending auth: status code %d

Error message

failed to get MCP pending auth: status code %d

What it means

MCPPendingAuth calls GET /workspaces/{id}/mcp/pending-auth and expects HTTP 200 with a JSON array of proto.MCPPendingAuthServer. When the server returns any other status code (401, 404, 500, 502...), the client wraps the status code in this error and returns no data. It signals the workspace MCP pending-auth lookup was rejected server-side, not a network or decoding failure.

Source

Thrown at internal/client/proto.go:340

		return nil, fmt.Errorf("failed to get MCP states: status code %d", rsp.StatusCode)
	}
	var states map[string]proto.MCPClientInfo
	if err := json.NewDecoder(rsp.Body).Decode(&states); err != nil {
		return nil, fmt.Errorf("failed to decode MCP states: %w", err)
	}
	return states, nil
}

// MCPPendingAuth retrieves the MCP servers awaiting OAuth authentication
// for a workspace.
func (c *Client) MCPPendingAuth(ctx context.Context, id string) ([]proto.MCPPendingAuthServer, error) {
	rsp, err := c.get(ctx, fmt.Sprintf("/workspaces/%s/mcp/pending-auth", id), nil, nil)
	if err != nil {
		return nil, fmt.Errorf("failed to get MCP pending auth: %w", err)
	}
	defer rsp.Body.Close()
	if rsp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("failed to get MCP pending auth: status code %d", rsp.StatusCode)
	}
	var pending []proto.MCPPendingAuthServer
	if err := json.NewDecoder(rsp.Body).Decode(&pending); err != nil {
		return nil, fmt.Errorf("failed to decode MCP pending auth: %w", err)
	}
	return pending, nil
}

// MCPAuthURL retrieves the current OAuth authorization URL for a named MCP
// server, if a flow is in progress.
func (c *Client) MCPAuthURL(ctx context.Context, id, name string) (string, error) {
	q := url.Values{"name": []string{name}}
	rsp, err := c.get(ctx, fmt.Sprintf("/workspaces/%s/mcp/auth-url", id), q, nil)
	if err != nil {
		return "", fmt.Errorf("failed to get MCP auth URL: %w", err)
	}
	defer rsp.Body.Close()
	if rsp.StatusCode != http.StatusOK {

View on GitHub (pinned to 7944b8e522)

Solutions

  1. Log the actual status code in the message and check it: 401/403 means fix credentials, 404 means the workspace id is wrong, 5xx means the server is unhealthy.
  2. Verify the workspace id passed to MCPPendingAuth exists and is reachable (list workspaces first or re-fetch it).
  3. Ensure the client is constructed with valid auth (same token/user the server expects) and pointed at the correct server URL/environment.
  4. For transient 5xx, retry with backoff; for 4xx, fix the request before retrying.

Example fix

// before
servers, err := client.MCPPendingAuth(ctx, "ws_123") // id guessed from an old config

// after
ws, err := client.Workspace(ctx) // resolve the real workspace id
if err != nil {
    return err
}
servers, err := client.MCPPendingAuth(ctx, ws.ID)
Defensive patterns

Strategy: retry

Validate before calling

// Best-effort preflight: ensure the workspace is resolvable before polling pending auth.
ws, err := client.Workspace(ctx)
if err != nil {
    return fmt.Errorf("workspace unavailable, skip MCPPendingAuth: %w", err)
}
if ws.ID == "" {
    return errors.New("no workspace id available for MCP pending auth")

Try / catch

servers, err := client.MCPPendingAuth(ctx, id)
if err != nil {
    var apiErr *client.StatusError // if the SDK exposes one; otherwise inspect the message
    if strings.Contains(err.Error(), "status code 5") {
        // transient: retry with backoff
        return retryWithBackoff(3, func() error { _, err = client.MCPPendingAuth(ctx, id); return err })
    }
    if strings.Contains(err.Error(), "status code 401") || strings.Contains(err.Error(), "status code 403") {
        return fmt.Errorf("re-authenticate required: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: Calling Client.MCPPendingAuth(ctx, id) where the HTTP response from /workspaces/{id}/mcp/pending-auth has StatusCode != http.StatusOK (e.g. invalid or expired workspace id, missing/invalid auth token causing 401, server error, or a proxy returning 502).

Common situations: Using a workspace id from a different environment, running against a server that requires auth headers the client isn't sending, the workspace having been deleted so the route 404s, or a load balancer/API gateway returning 5xx during server restarts or downtime.

Related errors


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