apache/beam · error · NoSuchElementException

Failed to list first page of FHIR resources from

Error message

Failed to list first page of FHIR resources from %s: %s

What it means

The FHIR store 'has any resources' check in HttpHealthcareApiClient throws NoSuchElementException when the initial FHIR search request throws IOException, converting an I/O/API failure into an empty-result signal for the hasNext() contract. The real cause (store not found, no permission, malformed request) is appended in the message.

Solutions

  1. Verify the fhirStore full resource path (projects/{p}/locations/{l}/datasets/{d}/fhirStores/{s})
  2. Grant roles/healthcare.fhirStoreViewer to the caller's service account
  3. Check the embedded IOException message for the actual HTTP cause
  4. Confirm the FHIR store exists via `gcloud healthcare fhir-stores describe` and retry on transient failures

Example fix

// before
throw new NoSuchElementException(String.format("Failed to list first page of FHIR resources from %s: %s", fhirStore, e.getMessage()));
// after
// validate store accessibility before iterating
try {
  boolean hasResources = client.hasFhirResources(fhirStore);
} catch (NoSuchElementException e) {
  throw new IOException("Cannot access FHIR store " + fhirStore + ": " + e.getMessage(), e);
}
Defensive patterns

Strategy: try-catch

Validate before calling

java
if (!fhirStore.matches("projects/[^/]+/locations/[^/]+/datasets/[^/]+/fhirStores/[^/]+")) {
  throw new IllegalArgumentException("Malformed fhirStore path: " + fhirStore);
}

Try / catch

java
try {
  hasResources = checkFirstPage(fhirStore);
} catch (NoSuchElementException e) {
  throw new IOException("FHIR store unreachable: " + e.getMessage(), e);
}

Prevention

When it happens

Trigger: Calling the method that checks for the first page of FHIR resources (used by FhirIO source hasNext) when the FHIR stores.search/.list REST request fails: wrong fhirStore path, missing healthcare.fhirStoreViewer IAM role, network outage, or API error response.

Common situations: Misspelled datasets/{d}/fhirStores/{s} path; service account without FHIR read permissions; transient 5xx during a Beam FHIR import/export pipeline; FHIR store not yet created.

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

Appendix: source

Thrown at sdks/java/io/google-cloud-platform/src/main/java/org/apache/beam/sdk/io/gcp/healthcare/HttpHealthcareApiClient.java:976

    public static FhirResourcePagesIterator ofPatientEverything(
        HealthcareApiClient client, String resourceName, @Nullable Map<String, Object> parameters) {
      return new FhirResourcePagesIterator(
          FhirMethod.PATIENT_EVERYTHING, client, "", "", resourceName, parameters);
    }

    @Override
    public boolean hasNext() throws NoSuchElementException {
      if (!isFirstRequest) {
        return this.pageToken != null && !this.pageToken.isEmpty();
      }
      try {
        HttpBody response = executeFhirRequest();
        JsonObject jsonResponse =
            JsonParser.parseString(mapper.writeValueAsString(response)).getAsJsonObject();
        JsonArray resources = jsonResponse.getAsJsonArray("entry");
        return resources != null && resources.size() != 0;
      } catch (IOException e) {
        throw new NoSuchElementException(
            String.format(
                "Failed to list first page of FHIR resources from %s: %s",
                fhirStore, e.getMessage()));
      }
    }

    @Override
    public JsonArray next() throws NoSuchElementException {
      try {
        HttpBody response = executeFhirRequest();
        this.isFirstRequest = false;
        JsonObject jsonResponse =
            JsonParser.parseString(mapper.writeValueAsString(response)).getAsJsonObject();
        JsonArray links = jsonResponse.getAsJsonArray("link");
        this.pageToken = parsePageToken(links);
        JsonArray resources = jsonResponse.getAsJsonArray("entry");
        return resources;
      } catch (IOException e) {

View on GitHub (pinned to 12126d8942)