apache/beam · error

read resource request returned error on input

Error message

read resource request returned error on input: [%v]

What it means

readResourceFn.ProcessElement calls client.readResource(resourcePath) to GET a single FHIR resource. If the HTTP request fails, the error is wrapped with this message including the input resource path and emitted to the dead-letter channel; the element is not retried automatically by fhirio.

Solutions

  1. Verify each resourcePath is a valid full FHIR resource path and the resource exists (curl the URL directly)
  2. Check worker network egress to healthcare.googleapis.com (VPC settings, firewall)
  3. Validate credentials/scopes (cloud-healthcare scope, ADC configured on workers)
  4. Implement a retry/dead-letter replay: read emitDeadLetter output and reprocess failed paths with backoff
  5. Confirm the FHIR store was not deleted/moved mid-pipeline

Example fix

// before
emitDeadLetter(errors.Wrapf(err, "read resource request returned error on input: [%v]", resourcePath).Error())
// after
if isTransient(err) {
    return retryRead(resourcePath, 3) // exponential backoff
}
emitDeadLetter(errors.Wrapf(err, "read resource request returned error on input: [%v]", resourcePath).Error())
Defensive patterns

Strategy: retry

Validate before calling

resourcePath := "projects/p/locations/l/datasets/d/fhirStores/s/fhir/Patient/123"
parts := strings.Split(resourcePath, "/")
if len(parts) != 10 || parts[8] != "fhir" { return fmt.Errorf("bad resource path: %s", resourcePath) }

Try / catch

// wrap reads with backoff retry for transient errors
for attempt := 0; attempt < 3; attempt++ {
    resp, err := client.readResource(path)
    if err == nil { return resp }
    if !isTransient(err) { break }
    time.Sleep(backoff(attempt))
}

Prevention

When it happens

Trigger: fn.client.readResource(resourcePath) returns a non-nil error: DNS/network failure, invalid resourcePath (malformed projects/.../fhirStores/<s>/fhir/<type>/<id> path), timeouts, or a failed access token refresh inside the client.

Common situations: Resource ID typos in the source PCollection; store deleted or renamed between pipeline stages; no network from Dataflow workers; expired/insufficient credentials for the Healthcare API.

Understand the failure class

Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.

Related errors


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

Appendix: source

Thrown at sdks/go/pkg/beam/io/fhirio/read.go:52

type readResourceFn struct {
	fnCommonVariables
}

func (fn readResourceFn) String() string {
	return "readResourceFn"
}

func (fn *readResourceFn) Setup() {
	fn.fnCommonVariables.setup(fn.String())
}

func (fn *readResourceFn) ProcessElement(ctx context.Context, resourcePath []byte, emitResource, emitDeadLetter func(string)) {
	response, err := executeAndRecordLatency(ctx, &fn.latencyMs, func() (*http.Response, error) {
		return fn.client.readResource(resourcePath)
	})
	if err != nil {
		fn.resourcesErrorCount.Inc(ctx, 1)
		emitDeadLetter(errors.Wrapf(err, "read resource request returned error on input: [%v]", resourcePath).Error())
		return
	}

	body, err := extractBodyFrom(response)
	if err != nil {
		fn.resourcesErrorCount.Inc(ctx, 1)
		emitDeadLetter(errors.Wrapf(err, "could not extract body from read resource [%v] response", resourcePath).Error())
		return
	}

	fn.resourcesSuccessCount.Inc(ctx, 1)
	emitResource(body)
}

// Read fetches resources from Google Cloud Healthcare FHIR stores based on the
// resource path. It consumes a PCollection<string> of notifications from the
// FHIR store of resource paths, and fetches the actual resource object on the
// path in the notification. It outputs two PCollection<string>. The first

View on GitHub (pinned to 12126d8942)