{"record":{"id":"815ab3ff66f7099d","repo":"apache/beam","slug":"could-not-extract-body-from-read-resource-v-response","errorCode":null,"errorMessage":"could not extract body from read resource [%v] response","messagePattern":"could not extract body from read resource \\[(.+?)\\] response","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"sdks/go/pkg/beam/io/fhirio/read.go","lineNumber":59,"sourceCode":"\nfunc (fn *readResourceFn) Setup() {\n\tfn.fnCommonVariables.setup(fn.String())\n}\n\nfunc (fn *readResourceFn) ProcessElement(ctx context.Context, resourcePath []byte, emitResource, emitDeadLetter func(string)) {\n\tresponse, err := executeAndRecordLatency(ctx, &fn.latencyMs, func() (*http.Response, error) {\n\t\treturn fn.client.readResource(resourcePath)\n\t})\n\tif err != nil {\n\t\tfn.resourcesErrorCount.Inc(ctx, 1)\n\t\temitDeadLetter(errors.Wrapf(err, \"read resource request returned error on input: [%v]\", resourcePath).Error())\n\t\treturn\n\t}\n\n\tbody, err := extractBodyFrom(response)\n\tif err != nil {\n\t\tfn.resourcesErrorCount.Inc(ctx, 1)\n\t\temitDeadLetter(errors.Wrapf(err, \"could not extract body from read resource [%v] response\", resourcePath).Error())\n\t\treturn\n\t}\n\n\tfn.resourcesSuccessCount.Inc(ctx, 1)\n\temitResource(body)\n}\n\n// Read fetches resources from Google Cloud Healthcare FHIR stores based on the\n// resource path. It consumes a PCollection<string> of notifications from the\n// FHIR store of resource paths, and fetches the actual resource object on the\n// path in the notification. It outputs two PCollection<string>. The first\n// contains the fetched object as a JSON-encoded string, and the second is a\n// dead-letter with an error message, in case the object failed to be fetched.\n// See: https://cloud.google.com/healthcare-api/docs/how-tos/fhir-resources#getting_a_fhir_resource.\nfunc Read(s beam.Scope, resourcePaths beam.PCollection) (beam.PCollection, beam.PCollection) {\n\ts = s.Scope(\"fhirio.Read\")\n\treturn read(s, resourcePaths, nil)\n}","sourceCodeStart":41,"sourceCodeEnd":77,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/go/pkg/beam/io/fhirio/read.go#L41-L77","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Check the wrapped cause in the dead-letter message for the HTTP status","Re-verify the resource exists and the caller has healthcare.fhirResources.get permission","Retry the read — GETs are idempotent and transient resets are common","Bypass proxies that break streaming; inspect worker logs for connection-reset patterns","Update the SDK so status codes are surfaced clearly before body extraction"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// pre-check access with a lightweight read\nresp, err := client.readResource(testPath)\nif err != nil || resp.StatusCode != http.StatusOK {\n    return fmt.Errorf(\"cannot read test resource: status %v\", resp.StatusCode)\n}","typeGuard":null,"tryCatchPattern":"// read emitDeadLetter output and retry failures\nbeam.ParDo(s, &replayDeadLetters{MaxAttempts: 3}, deadLetters)","preventionTips":["Grant healthcare.fhirResources.get to the pipeline service account","Check permissions/403s in the wrapped dead-letter message","Avoid large streaming reads through unstable proxies","Retry idempotent GETs with backoff"],"tags":["go","fhirio","http-response"],"backgroundTag":"http-error-response","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-20T03:17:13.778Z"}