apache/beam · error

failed to get metrics

Error message

failed to get metrics

What it means

newDataflowPipelineResult fetches a Dataflow job's metric updates via GetMetrics to populate the pipeline result. If the GetMetrics API call fails, the error is wrapped with 'failed to get metrics' and a result with a nil metrics field is returned. This means the SDK could not read the job's final counters from the Dataflow API.

Solutions

  1. Retry — GetMetrics failures are often transient; the job may have completed fine
  2. Verify the service account can read job metrics (roles/dataflow.viewer or equivalent)
  3. Check project/region/jobID are correct in the metrics request
  4. Inspect the wrapped error for the HTTP status and act on it (403 → permissions, 404 → wrong region/job, 5xx → retry)
Defensive patterns

Strategy: retry

Try / catch

if err := run(); err != nil && strings.Contains(err.Error(), "failed to get metrics") {
    // retry with backoff; job itself may have succeeded
    time.Sleep(10 * time.Second)
}

Prevention

When it happens

Trigger: Calling Execute (which calls newDataflowPipelineResult after job completion) when the Dataflow projects.locations.jobs.getMetrics request fails: network error, transient API 5xx, invalid job ID, or insufficient permissions.

Common situations: Transient Google API outages right at job completion, service accounts lacking monitoring/viewer or dataflow viewer roles, very fresh jobs whose metrics endpoint briefly 404s, or corporate proxies blocking googleapis.com.

Understand the failure class

Background: "API request failed": what wrapped HTTP errors from external APIs mean and how to find the real cause — this error's family across 29 libraries.

Related errors


AI-assisted analysis of apache/beam@12126d8942 (2026-09-13). Data as JSON: /api/errors/abfa16b19a161fb1. Report an issue: GitHub.

Appendix: source

Thrown at sdks/go/pkg/beam/runners/dataflow/dataflowlib/execute.go:173

// PrintJob logs the Dataflow job.
func PrintJob(ctx context.Context, job *df.Job) {
	str, err := json.MarshalIndent(job, "", "  ")
	if err != nil {
		log.Infof(ctx, "Failed to print job %v: %v", job.Id, err)
	}
	log.Info(ctx, string(str))
}

type dataflowPipelineResult struct {
	jobID   string
	metrics *metrics.Results
}

func newDataflowPipelineResult(ctx context.Context, client *df.Service, p *pipepb.Pipeline, project, region, jobID string) (*dataflowPipelineResult, error) {
	res, err := GetMetrics(ctx, client, project, region, jobID)
	if err != nil {
		return &dataflowPipelineResult{jobID, nil}, errors.Wrap(err, "failed to get metrics")
	}
	return &dataflowPipelineResult{jobID, FromMetricUpdates(res.Metrics, p)}, nil
}

func (pr dataflowPipelineResult) Metrics() metrics.Results {
	return *pr.metrics
}

func (pr dataflowPipelineResult) JobID() string {
	return pr.jobID
}

View on GitHub (pinned to 12126d8942)