googleapis/mcp-toolbox · error

failed to update cluster: %w

Error message

failed to update cluster: %w

What it means

This error wraps any failure returned by the Cloud Bigtable InstanceAdmin client's UpdateCluster call when the MCP tool invokes Source.UpdateCluster. The library wraps the underlying gRPC/API error with fmt.Errorf("failed to update cluster: %w", err), so the original cause (permissions, not found, quota, invalid nodes) is preserved via the %w chain. Inspect the wrapped error with errors.Unwrap or %v to see the real gRPC status.

Source

Thrown at internal/sources/bigtable/admin_wrappers.go:118

func (s *Source) CreateCluster(ctx context.Context, instanceId, clusterId, zone string, numNodes int32) (any, error) {
	conf := &bigtable.ClusterConfig{
		InstanceID: instanceId,
		ClusterID:  clusterId,
		Zone:       zone,
		NumNodes:   numNodes,
	}
	err := s.InstanceAdmin.CreateCluster(ctx, conf)
	if err != nil {
		return nil, fmt.Errorf("failed to create cluster: %w", err)
	}
	return map[string]string{"status": "cluster created successfully"}, nil
}

func (s *Source) UpdateCluster(ctx context.Context, instanceId, clusterId string, serveNodes int32) (any, error) {
	err := s.InstanceAdmin.UpdateCluster(ctx, instanceId, clusterId, serveNodes)
	if err != nil {
		return nil, fmt.Errorf("failed to update cluster: %w", err)
	}
	return map[string]string{"status": "cluster updated successfully"}, nil
}

func (s *Source) DeleteCluster(ctx context.Context, instanceId, clusterId string) (any, error) {
	err := s.InstanceAdmin.DeleteCluster(ctx, instanceId, clusterId)
	if err != nil {
		return nil, fmt.Errorf("failed to delete cluster: %w", err)
	}
	return map[string]string{"status": "cluster deleted successfully"}, nil
}

func (s *Source) GetTable(ctx context.Context, tableId string) (any, error) {
	table, err := s.Admin.TableInfo(ctx, tableId)
	if err != nil {
		return nil, fmt.Errorf("failed to get table: %w", err)
	}
	return table, nil

View on GitHub (pinned to 8cc6e09de2)

Solutions

  1. Verify instanceId and clusterId exist (list instances/clusters via admin console or bigtable list tools) and use the ID, not the display name.
  2. Check IAM: the caller's service account needs roles/bigtable.admin (or at least bigtable.clusters.update).
  3. Inspect the wrapped error (gRPC status code) to distinguish NotFound vs PermissionDenied vs ResourceExhausted; fix the corresponding cause.
  4. Retry transient failures (Unavailable/DeadlineExceeded) with backoff; check node quota if ResourceExhausted.

Example fix

// before: blindly wrapping without surfacing the gRPC status
return nil, fmt.Errorf("failed to update cluster: %w", err)
// after: caller-side discrimination of the wrapped error
var st *status.Status
if errors.As(err, &st) && st.Code() == codes.NotFound {
    log.Printf("cluster %s not found in instance %s", clusterId, instanceId)
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Go: verify inputs before calling UpdateCluster
if instanceId == "" || clusterId == "" {
    return fmt.Errorf("instanceId and clusterId are required")
}
if serveNodes <= 0 {
    return fmt.Errorf("serveNodes must be a positive integer")
}

Type guard

func isNotFound(err error) bool {
    return status.Code(err) == codes.NotFound
}

Try / catch

if err := src.UpdateCluster(ctx, inst, cluster, nodes); err != nil {
    switch status.Code(err) {
    case codes.NotFound:
        // handle missing cluster
    case codes.PermissionDenied:
        // surface IAM guidance
    case codes.Unavailable, codes.DeadlineExceeded:
        // retry with backoff
    default:
        log.Printf("update cluster failed: %v", err)
    }
}

Prevention

When it happens

Trigger: Calling the bigtable update_cluster tool (Source.UpdateCluster in internal/sources/bigtable/admin_wrappers.go:118) where s.InstanceAdmin.UpdateCluster(ctx, instanceId, clusterId, serveNodes) returns a non-nil error: instance or cluster ID does not exist, caller lacks bigtable.clusters.update IAM permission, serveNodes value is invalid, or the gRPC call fails (timeout, network, quota).

Common situations: Typo in instanceId/clusterId (IDs are distinct from display names); service account missing Bigtable Admin role; autoscaling-enabled clusters rejecting manual serveNodes changes; transient gRPC Unavailable during zone maintenance; exceeding node quota in a region.

Related errors


AI-assisted analysis of googleapis/mcp-toolbox@8cc6e09de2 (2026-09-05). Data as JSON: /api/errors/85756e478b314141. Report an issue: GitHub.