apache/beam · error

could not extract body from read resource

Error message

could not extract body from read resource [%v] response

What it means

After a successful readResource HTTP call, extractBodyFrom reads the response payload. If reading fails or the status is unusable, fhirio cannot produce the resource JSON, so it wraps the cause with this message (including the resource path) and emits it to the dead-letter channel.

Solutions

  1. Check the wrapped cause in the dead-letter message for the HTTP status
  2. Re-verify the resource exists and the caller has healthcare.fhirResources.get permission
  3. Retry the read — GETs are idempotent and transient resets are common
  4. Bypass proxies that break streaming; inspect worker logs for connection-reset patterns
  5. Update the SDK so status codes are surfaced clearly before body extraction
Defensive patterns

Strategy: retry

Validate before calling

// pre-check access with a lightweight read
resp, err := client.readResource(testPath)
if err != nil || resp.StatusCode != http.StatusOK {
    return fmt.Errorf("cannot read test resource: status %v", resp.StatusCode)
}

Try / catch

// read emitDeadLetter output and retry failures
beam.ParDo(s, &replayDeadLetters{MaxAttempts: 3}, deadLetters)

Prevention

When it happens

Trigger: extractBodyFrom(response) errors after readResource succeeded at the transport level: body read I/O error, or a non-2xx status that extractBodyFrom treats as fatal (e.g. 404/403 surfaces here if the client does not reject it earlier).

Common situations: Connection reset while streaming a large resource; an intermediary returning error responses with bodies that cannot be extracted; wrong permissions yielding 403 bodies; resource deleted between request send and response handling.

Understand the failure class

Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.

Related errors


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

Appendix: source

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

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
// contains the fetched object as a JSON-encoded string, and the second is a
// dead-letter with an error message, in case the object failed to be fetched.
// See: https://cloud.google.com/healthcare-api/docs/how-tos/fhir-resources#getting_a_fhir_resource.
func Read(s beam.Scope, resourcePaths beam.PCollection) (beam.PCollection, beam.PCollection) {
	s = s.Scope("fhirio.Read")
	return read(s, resourcePaths, nil)
}

View on GitHub (pinned to 12126d8942)