googleapis/mcp-toolbox · error

failed to list data assets: code=%s message=%s

Error message

failed to list data assets: code=%s message=%s

What it means

While iterating DataAsset results in ListDataAssets, the call returned a gRPC error with a structured status; the library surfaces the status code and message in this error. It means the Dataplex API itself rejected the ListDataAssets request.

Source

Thrown at internal/sources/dataplex/dataplex.go:578

	parent := fmt.Sprintf("projects/%s/locations/%s/dataProducts/%s", s.ProjectID(), locationID, dataProductID)
	req := &dataplexpb.ListDataAssetsRequest{
		Parent:   parent,
		Filter:   filter,
		PageSize: int32(pageSize),
		OrderBy:  orderBy,
	}

	it := s.GetDataProductClient().ListDataAssets(ctx, req)
	var results []*DataAsset

	for len(results) < pageSize {
		asset, err := it.Next()
		if err == iterator.Done {
			break
		}
		if err != nil {
			if st, ok := grpcstatus.FromError(err); ok {
				return nil, fmt.Errorf("failed to list data assets: code=%s message=%s", st.Code(), st.Message())
			}
			return nil, fmt.Errorf("failed to list data assets: %w", err)
		}
		parts := strings.Split(asset.GetName(), "/")
		var locID, prodID, assetID string
		if len(parts) >= 8 && parts[0] == "projects" && parts[2] == "locations" && parts[4] == "dataProducts" && parts[6] == "dataAssets" {
			locID = parts[3]
			prodID = parts[5]
			assetID = parts[7]
		}
		results = append(results, &DataAsset{
			LocationID:    locID,
			DataProductID: prodID,
			DataAssetID:   assetID,
			ResourceURI:   asset.GetResource(),
			Labels:        asset.GetLabels(),
		})
	}

View on GitHub (pinned to 8cc6e09de2)

Solutions

  1. Read the embedded code= and message= fields to identify the exact gRPC status.
  2. Grant the service account dataplex.dataAssets.list permission (roles/dataplex.viewer/dataReader).
  3. Verify the location ID and data product ID in the parent resource name exist.
  4. Check filter/orderBy syntax against the Dataplex ListDataAssets reference.

Example fix

// before (deleted product)
prodID := "old-product"
// after (verify first)
products, err := src.ListDataProducts(ctx, "", 50, "") // confirm prodID still listed
Defensive patterns

Strategy: try-catch

Validate before calling

if locationID == "" || dataProductID == "" {
	return errors.New("locationID and dataProductID are required")
}

Type guard

func isNotFound(err error) bool {
	st, ok := status.FromError(err)
	return ok && st.Code() == codes.NotFound
}

Try / catch

assets, err := src.ListDataAssets(ctx, locID, prodID, filter, pageSize, orderBy)
if err != nil {
	if isNotFound(err) {
		return fmt.Errorf("data product %q not found in %s: %w", prodID, locID, err)
	}
	if isPermissionDenied(err) {
		return fmt.Errorf("grant dataplex.dataReader IAM: %w", err)
	}
	return err
}

Prevention

When it happens

Trigger: The parent 'projects/{p}/locations/{l}/dataProducts/{id}' is wrong (bad location or data product ID), the caller lacks dataplex.dataAssets.list permission, or the filter/orderBy expression is invalid.

Common situations: Service account missing roles/dataplex.viewer or dataplex.dataReader; referencing a data product that was deleted; invalid filter field names; Dataplex API not enabled in the project.

Related errors


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