{"record":{"id":"782a4b5578761c6c","repo":"apache/beam","slug":"the-pcollection-tuple-must-have-the-fhiriopatienteverything","errorCode":null,"errorMessage":"The PCollection tuple must have the FhirIOPatientEverything.OUT and FhirIOPatientEverything.DEAD_LETTER tuple tags","messagePattern":"The PCollection tuple must have the FhirIOPatientEverything\\.OUT and FhirIOPatientEverything\\.DEAD_LETTER tuple tags","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"sdks/java/io/google-cloud-platform/src/main/java/org/apache/beam/sdk/io/gcp/healthcare/FhirIOPatientEverything.java","lineNumber":115,"sourceCode":"  public static class Result implements POutput, PInput {\n\n    private final PCollection<JsonArray> patientCompartments;\n    private final PCollection<HealthcareIOError<String>> failedReads;\n\n    PCollectionTuple pct;\n\n    /**\n     * Create FhirIOPatientEverything.Result form PCollectionTuple with OUT and DEAD_LETTER tags.\n     *\n     * @param pct the pct\n     * @return the patient everything result\n     * @throws IllegalArgumentException the illegal argument exception\n     */\n    static Result of(PCollectionTuple pct) throws IllegalArgumentException {\n      if (pct.has(OUT) && pct.has(DEAD_LETTER)) {\n        return new Result(pct);\n      } else {\n        throw new IllegalArgumentException(\n            \"The PCollection tuple must have the FhirIOPatientEverything.OUT \"\n                + \"and FhirIOPatientEverything.DEAD_LETTER tuple tags\");\n      }\n    }\n\n    private Result(PCollectionTuple pct) {\n      this.pct = pct;\n      this.patientCompartments = pct.get(OUT).setCoder(JsonArrayCoder.of());\n      this.failedReads =\n          pct.get(DEAD_LETTER).setCoder(HealthcareIOErrorCoder.of(StringUtf8Coder.of()));\n    }\n\n    /**\n     * Gets failed reads.\n     *\n     * @return the failed reads\n     */\n    public PCollection<HealthcareIOError<String>> getFailedReads() {","sourceCodeStart":97,"sourceCodeEnd":133,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/io/google-cloud-platform/src/main/java/org/apache/beam/sdk/io/gcp/healthcare/FhirIOPatientEverything.java#L97-L133","documentation":"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.","triggerScenarios":"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().","commonSituations":"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.","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."],"exampleFix":"// before\nPCollectionTuple pct = pipeline.apply(new FhirIOPatientEverything())\n    .get(\"out\", TypeDescriptors.strings());\nResult r = FhirIOPatientEverything.Result.of(pct); // throws\n\n// after\nPCollection<FhirSearchOutcome> main = ...;\nPCollection<FhirSearchOutcome> dead = ...;\nPCollectionTuple pct = main.apply(...) instanceof PCollectionTuple ? null : null;\n// correct pattern:\nPCollectionTuple pct2 = PCollectionTuple.of(FhirIOPatientEverything.OUT, main,\n    FhirIOPatientEverything.DEAD_LETTER, dead);\nResult r2 = FhirIOPatientEverything.Result.of(pct2);","handlingStrategy":"validation","validationCode":"boolean ok = pct.has(FhirIOPatientEverything.OUT) && pct.has(FhirIOPatientEverything.DEAD_LETTER);\nif (!ok) throw new IllegalArgumentException(\"Tuple must use FhirIOPatientEverything.OUT/DEAD_LETTER tags\");","typeGuard":"boolean isFhirPatientEverythingResult(PCollectionTuple pct) {\n  return pct.has(FhirIOPatientEverything.OUT) && pct.has(FhirIOPatientEverything.DEAD_LETTER);\n}","tryCatchPattern":"try {\n  Result r = FhirIOPatientEverything.Result.of(pct);\n} catch (IllegalArgumentException e) {\n  throw new IllegalStateException(\"Pipeline wiring bug: wrong tuple tags for FhirIOPatientEverything\", e);\n}","preventionTips":["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."],"tags":["java","apache-beam","google-cloud-healthcare","pcollectiontuple","illegal-argument"],"backgroundTag":"missing-required-argument","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}