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
- 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, ...)).
- Check that the tags used are the static constants from FhirIOPatientEverything, not re-declared TupleTags with the same id in a different class.
- If only the main output exists in your pipeline, still create and populate the DEAD_LETTER PCollection before calling Result.of.
- 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
- Always build the tuple from the transform's expand() output instead of hand-constructing it.
- Reference the OUT/DEAD_LETTER constants directly; never redeclare TupleTags with the same ids.
- Add a pipeline-construction unit test asserting Result.of succeeds on your wired tuple.
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
- The PCollection tuple must have the HL7v2IO.Read.OUT and HL7
- The PCollection tuple must have the HL7v2IO.HL7v2Read.OUT an
- ApproximateUnique.PerKey needs an estimation error between 1
- timerFrequency must be greater than zero
- label + ": " + String.format(message, args)
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/782a4b5578761c6c.
Report an issue: GitHub.