googleapis/mcp-toolbox · error

failed to list jobs: %w

Error message

failed to list jobs: %w

What it means

ListJobs wraps any error returned by the Dataproc pager while iterating a page of jobs (pager.NextPage). This library wraps the underlying Google API error with %w so callers can inspect it with errors.Is/As. It indicates the RPC to the Dataproc API failed while listing jobs in the configured region.

Source

Thrown at internal/sources/dataproc/dataproc.go:313

	if jobStateMatcher != "" {
		if v, ok := dataprocpb.ListJobsRequest_JobStateMatcher_value[jobStateMatcher]; ok {
			req.JobStateMatcher = dataprocpb.ListJobsRequest_JobStateMatcher(v)
		} else {
			return nil, fmt.Errorf("invalid jobStateMatcher: %s. Supported values: ALL, ACTIVE, NON_ACTIVE", jobStateMatcher)
		}
	}

	it := client.ListJobs(ctx, req)
	ps := 0
	if pageSize != nil {
		ps = *pageSize
	}
	pager := iterator.NewPager(it, ps, req.PageToken)

	var jobPbs []*dataprocpb.Job
	nextPageToken, err := pager.NextPage(&jobPbs)
	if err != nil {
		return nil, fmt.Errorf("failed to list jobs: %w", err)
	}

	jobs, err := ToJobs(jobPbs, s.Region)
	if err != nil {
		return nil, err
	}

	return ListJobsResponse{Jobs: jobs, NextPageToken: nextPageToken}, nil
}

// ToJobs converts a slice of protobuf Job messages to a slice of Job structs.
func ToJobs(jobPbs []*dataprocpb.Job, region string) ([]Job, error) {
	jobs := make([]Job, 0, len(jobPbs))
	for _, jobPb := range jobPbs {
		consoleUrl := JobConsoleURLFromProto(jobPb, region)
		logsUrl, err := JobLogsURLFromProto(jobPb, region)
		if err != nil {
			return nil, fmt.Errorf("error generating logs url: %v", err)

View on GitHub (pinned to 8cc6e09de2)

Solutions

  1. Unwrap the error (errors.Unwrap / %v formatting) to see the underlying gRPC status and act on it
  2. Verify the region in the Dataproc source config matches where the cluster/jobs live (use 'global' or the correct regional endpoint)
  3. Grant the caller's service account the dataproc.jobs.list permission (roles/dataproc.viewer or roles/dataproc.editor)
  4. Enable the Dataproc API on the project and check quota/limits
  5. Retry on transient errors with backoff

Example fix

// before
jobs, err := toolbox.ListJobs(ctx, pageSize, token)
// after
jobs, err := toolbox.ListJobs(ctx, pageSize, token)
if err != nil {
	log.Printf("list jobs failed: %v", err) // wrapped gRPC error shows real cause
	if st, ok := status.FromError(errors.Unwrap(err)); ok && st.Code() == codes.PermissionDenied { ... }
}
Defensive patterns

Strategy: try-catch

Validate before calling

if region == "" || projectID == "" {
	return fmt.Errorf("region and projectId must be set before listing Dataproc jobs")
}

Try / catch

jobs, err := svc.ListJobs(ctx, pageSize, token)
if err != nil {
	if u := errors.Unwrap(err); u != nil && strings.Contains(u.Error(), "PermissionDenied") {
		// fix IAM
	}
	return fmt.Errorf("listing dataproc jobs: %w", err)
}

Prevention

When it happens

Trigger: Calling ListJobs when the Dataproc API call fails: invalid/missing region, disabled Dataproc API, insufficient IAM permissions (dataproc.jobs.list), network failure, or an invalid page token.

Common situations: Misconfigured region in the source config (e.g. region set to a location with no projects access), service account lacking roles/dataproc.viewer, quota exhaustion, or transient 5xx from the Dataproc API.

Related errors


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