apache/beam · error · IllegalArgumentException

The PCollection tuple must have the FhirIOPatientEverything.

Error message

The PCollection tuple must have the FhirIOPatientEverything.OUT and FhirIOPatientEverything.DEAD_LETTER tuple tags

What it means

FhirIOPatientEverything.Result.of() validates that the supplied PCollectionTuple contains PCollections registered under exactly the FhirIOPatientEverything.OUT and FhirIOPatientEverything.DEAD_LETTER TupleTags before wrapping it in a Result. If either tag is absent, the tuple cannot represent the output of the FhirIOPatientEverything transform, so the library fails fast with IllegalArgumentException rather than returning a Result with missing PCollections.

Source

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

  public static class Result implements POutput, PInput {

    private final PCollection<JsonArray> patientCompartments;
    private final PCollection<HealthcareIOError<String>> failedReads;

    PCollectionTuple pct;

    /**
     * Create FhirIOPatientEverything.Result form PCollectionTuple with OUT and DEAD_LETTER tags.
     *
     * @param pct the pct
     * @return the patient everything result
     * @throws IllegalArgumentException the illegal argument exception
     */
    static Result of(PCollectionTuple pct) throws IllegalArgumentException {
      if (pct.has(OUT) && pct.has(DEAD_LETTER)) {
        return new Result(pct);
      } else {
        throw new IllegalArgumentException(
            "The PCollection tuple must have the FhirIOPatientEverything.OUT "
                + "and FhirIOPatientEverything.DEAD_LETTER tuple tags");
      }
    }

    private Result(PCollectionTuple pct) {
      this.pct = pct;
      this.patientCompartments = pct.get(OUT).setCoder(JsonArrayCoder.of());
      this.failedReads =
          pct.get(DEAD_LETTER).setCoder(HealthcareIOErrorCoder.of(StringUtf8Coder.of()));
    }

    /**
     * Gets failed reads.
     *
     * @return the failed reads
     */
    public PCollection<HealthcareIOError<String>> getFailedReads() {

View on GitHub (pinned to 12126d8942)

Solutions

  1. Register both PCollections in the tuple using FhirIOPatientEverything.OUT and FhirIOPatientEverything.DEAD_LETTER as the TupleTags (pct.get(FhirIOPatientEverything.OUT, ...), pct.get(FhirIOPatientEverything.DEAD_LETTER, ...)).
  2. Check that the tags used are the static constants from FhirIOPatientEverything, not re-declared TupleTags with the same id in a different class.
  3. If only the main output exists in your pipeline, still create and populate the DEAD_LETTER PCollection before calling Result.of.
  4. Apply the FhirIOPatientEverything transform itself to produce the tuple (expand()) rather than hand-assembling it when possible.

Example fix

// before
PCollectionTuple pct = pipeline.apply(new FhirIOPatientEverything())
    .get("out", TypeDescriptors.strings());
Result r = FhirIOPatientEverything.Result.of(pct); // throws

// after
PCollection<FhirSearchOutcome> main = ...;
PCollection<FhirSearchOutcome> dead = ...;
PCollectionTuple pct = main.apply(...) instanceof PCollectionTuple ? null : null;
// correct pattern:
PCollectionTuple pct2 = PCollectionTuple.of(FhirIOPatientEverything.OUT, main,
    FhirIOPatientEverything.DEAD_LETTER, dead);
Result r2 = FhirIOPatientEverything.Result.of(pct2);
Defensive patterns

Strategy: validation

Validate before calling

boolean ok = pct.has(FhirIOPatientEverything.OUT) && pct.has(FhirIOPatientEverything.DEAD_LETTER);
if (!ok) throw new IllegalArgumentException("Tuple must use FhirIOPatientEverything.OUT/DEAD_LETTER tags");

Type guard

boolean isFhirPatientEverythingResult(PCollectionTuple pct) {
  return pct.has(FhirIOPatientEverything.OUT) && pct.has(FhirIOPatientEverything.DEAD_LETTER);
}

Try / catch

try {
  Result r = FhirIOPatientEverything.Result.of(pct);
} catch (IllegalArgumentException e) {
  throw new IllegalStateException("Pipeline wiring bug: wrong tuple tags for FhirIOPatientEverything", e);
}

Prevention

When it happens

Trigger: Calling FhirIOPatientEverything.Result.of(pct) with a PCollectionTuple that was populated with different TupleTags (e.g. custom tags or tags from another IO transform) or with only one of the two required tags (OUT or DEAD_LETTER) applied via pct.get().

Common situations: Developers building a pipeline that applies FhirIOPatientEverything and wire the outputs into a tuple using their own TupleTag names instead of the static OUT/DEAD_LETTER constants; copy-pasting HL7v2IO.Result code and forgetting to change the tags; forgetting to add the DEAD_LETTER PCollection when only the main output is written.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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