googleapis/mcp-toolbox · error

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

Error message

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

What it means

While iterating DataProduct results in ListDataProducts, the underlying call returned a gRPC error with a structured status. The library extracts the status code and message and returns them in this formatted error so the API-reported failure reason (e.g. PERMISSION_DENIED, INVALID_ARGUMENT) is directly visible.

Source

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

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

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

	for len(results) < pageSize {
		dp, 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 products: code=%s message=%s", st.Code(), st.Message())
			}
			return nil, fmt.Errorf("failed to list data products: %w", err)
		}
		parts := strings.Split(dp.GetName(), "/")
		var locID, prodID string
		if len(parts) >= 6 && parts[0] == "projects" && parts[2] == "locations" && parts[4] == "dataProducts" {
			locID = parts[3]
			prodID = parts[5]
		}
		results = append(results, &DataProductSummary{
			LocationID:    locID,
			DataProductID: prodID,
			DisplayName:   dp.GetDisplayName(),
			OwnerEmails:   dp.GetOwnerEmails(),
			AssetCount:    dp.GetAssetCount(),
		})
	}
	return results, nil

View on GitHub (pinned to 8cc6e09de2)

Solutions

  1. Read the embedded code= and message= to identify the exact gRPC status.
  2. Verify the service account has dataplex.dataProducts.list permission (grant roles/dataplex.viewer or equivalent).
  3. Confirm the Dataplex API is enabled on the project (gcloud services enable dataplex.googleapis.com).
  4. Check the project ID and filter/orderBy syntax against the Dataplex ListDataProducts API reference.

Example fix

// before (bad filter)
filter := "system = unknown"
// after (valid filter)
filter := "system = BIGQUERY"
Defensive patterns

Strategy: try-catch

Validate before calling

// preflight permission/parent check
if projectID == "" || !strings.Contains(projectID, "-") == false && projectID == "" { /* validate non-empty project */ }
if projectID == "" { return errors.New("project ID must be non-empty") }

Type guard

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

Try / catch

products, err := src.ListDataProducts(ctx, filter, pageSize, orderBy)
if err != nil {
	var re *googleapi.Error
	if isPermissionDenied(err) {
		return fmt.Errorf("grant roles/dataplex.viewer to the service account: %w", err)
	}
	return err
}

Prevention

When it happens

Trigger: The ListDataProducts iterator's Next() returns a gRPC status error, typically because the parent 'projects/{project}/locations/-' is malformed, the caller lacks dataplex.dataProducts.list IAM permission, the filter/orderBy string is invalid, or the project/location does not exist.

Common situations: Service account missing roles/dataplex.viewer; typo in project ID; invalid filter syntax such as an unknown field; calling against a project where the Dataplex API is not enabled.

Related errors


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