apache/beam · error

could not extract body from execute bundles response

Error message

could not extract body from execute bundles response

What it means

After a successful executeBundle HTTP response, fhirio calls extractBodyFrom to read and decode the response body. If reading the body (or validating the HTTP status inside extractBodyFrom) fails, the bundle's outcome cannot be determined, so the error is wrapped with this message and emitted to the failure channel.

Solutions

  1. Log the full response (status + headers) at the HTTP client level to identify the failing status code
  2. Inspect the emitted failure string for the wrapped extractBodyFrom cause (e.g. non-2xx status)
  3. Retry the bundle — executeBundle is idempotent for most FHIR transaction bundles
  4. Check for intermediaries (proxy, WAF) that terminate streaming bodies
  5. Reduce bundle size to avoid timeouts/truncation on very large batches
Defensive patterns

Strategy: retry

Try / catch

// treat failures from emitFailure as retryable
failures := beam.ParDo(s, &collectFailures{}, bundleResults)
beam.ParDo(s, &retryWithBackoff{MaxAttempts: 3}, failures)

Prevention

When it happens

Trigger: extractBodyFrom(response) returns an error on the executeBundle response: the response body read fails (connection reset mid-body) or the HTTP status is not 2xx so the body cannot be treated as a success payload.

Common situations: FHIR server closing the connection while the body is streaming; proxies/load balancers returning error pages with non-200 status; truncated responses on large batch bundles over unstable networks (e.g. Dataflow workers with flaky egress).

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/620b3260931abb6e. Report an issue: GitHub.

Appendix: source

Thrown at sdks/go/pkg/beam/io/fhirio/execute_bundles.go:72

func (fn *executeBundleFn) Setup() {
	fn.fnCommonVariables.setup(fn.String())
	fn.successesCount = beam.NewCounter(fn.String(), baseMetricPrefix+"success_count")
}

func (fn *executeBundleFn) ProcessElement(ctx context.Context, inputBundleBody string, emitSuccess, emitFailure func(string)) {
	response, err := executeAndRecordLatency(ctx, &fn.latencyMs, func() (*http.Response, error) {
		return fn.client.executeBundle(fn.FhirStorePath, inputBundleBody)
	})
	if err != nil {
		fn.resourcesErrorCount.Inc(ctx, 1)
		emitFailure(errors.Wrap(err, "execute bundle request returned error").Error())
		return
	}

	body, err := extractBodyFrom(response)
	if err != nil {
		fn.resourcesErrorCount.Inc(ctx, 1)
		emitFailure(errors.Wrap(err, "could not extract body from execute bundles response").Error())
		return
	}

	fn.processResponseBody(ctx, body, emitSuccess, emitFailure)
}

func (fn *executeBundleFn) processResponseBody(ctx context.Context, body string, emitSuccess, emitFailure func(string)) {
	var bodyFields struct {
		Type    string `json:"type"`
		Entries []any  `json:"entry"`
	}

	err := json.NewDecoder(strings.NewReader(body)).Decode(&bodyFields)
	if err != nil {
		fn.resourcesErrorCount.Inc(ctx, 1)
		emitFailure(errors.Wrap(err, "could not parse body from execute bundle response").Error())
		return
	}

View on GitHub (pinned to 12126d8942)