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, nilView on GitHub (pinned to 8cc6e09de2)
Solutions
- Read the embedded code= and message= to identify the exact gRPC status.
- Verify the service account has dataplex.dataProducts.list permission (grant roles/dataplex.viewer or equivalent).
- Confirm the Dataplex API is enabled on the project (gcloud services enable dataplex.googleapis.com).
- 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
- Grant roles/dataplex.viewer (or dataProducts.list IAM) to the service account before use.
- Enable dataplex.googleapis.com on the target project.
- Validate project ID and filter/orderBy syntax against the API reference.
- Keep filter expressions simple and field names verified.
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
- failed to list data assets: code=%s message=%s
- failed to create Dataplex client for project %q: %w
- failed to update cluster: %w
- failed to delete cluster: %w
- failed to get table: %w
AI-assisted analysis of googleapis/mcp-toolbox@8cc6e09de2 (2026-09-05).
Data as JSON: /api/errors/b10865007aaac6b8.
Report an issue: GitHub.