{"record":{"id":"7aae6d140680c8f1","repo":"apache/beam","slug":"firestore-read-transform-does-not-expect-input-pcollections","errorCode":null,"errorMessage":"Firestore read transform does not expect input PCollections.","messagePattern":"Firestore read transform does not expect input PCollections\\.","errorType":"validation","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"sdks/java/io/google-cloud-platform/src/main/java/org/apache/beam/sdk/io/gcp/firestore/FirestoreReadSchemaTransformProvider.java","lineNumber":96,"sourceCode":"  }\n\n  @Override\n  public List<String> outputCollectionNames() {\n    return Collections.singletonList(OUTPUT_TAG_NAME);\n  }\n\n  private static class FirestoreReadSchemaTransform extends SchemaTransform {\n    private final FirestoreReadSchemaTransformConfiguration configuration;\n\n    FirestoreReadSchemaTransform(FirestoreReadSchemaTransformConfiguration configuration) {\n      configuration.validate();\n      this.configuration = configuration;\n    }\n\n    @Override\n    public PCollectionRowTuple expand(PCollectionRowTuple input) {\n      if (!input.getAll().isEmpty()) {\n        throw new IllegalStateException(\n            \"Firestore read transform does not expect input PCollections.\");\n      }\n\n      Schema schema = JsonUtils.beamSchemaFromJsonSchema(configuration.getSchema());\n      String projectId = resolveProjectId(input.getPipeline());\n      String databaseId = resolveDatabaseId(input.getPipeline());\n      String parent = FirestoreUtils.documentsRoot(projectId, databaseId);\n\n      PCollection<ListDocumentsRequest> requests =\n          input\n              .getPipeline()\n              .apply(\"CreateCollectionId\", Create.of(configuration.getCollectionId()))\n              .apply(\n                  \"BuildListDocumentsRequest\",\n                  ParDo.of(\n                      new DoFn<String, ListDocumentsRequest>() {\n                        @ProcessElement\n                        public void processElement(","sourceCodeStart":78,"sourceCodeEnd":114,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/io/google-cloud-platform/src/main/java/org/apache/beam/sdk/io/gcp/firestore/FirestoreReadSchemaTransformProvider.java#L78-L114","documentation":"FirestoreReadSchemaTransformProvider.ReadTransform is a source transform: it produces output rows and therefore requires an empty PCollectionRowTuple input. expand() eagerly validates this and throws IllegalStateException if any input PCollections were passed in, since a read cannot consume elements.","triggerScenarios":"Wiring a Firestore read SchemaTransform into a pipeline where PCollectionRowTuple.input contains one or more named PCollections — e.g. composing the read after another transform in a SchemaTransform composition that supplied inputs.","commonSituations":"Misusing the SchemaTransform API by chaining a read transform after a write/transform; building a pipeline graph where the read node is accidentally given an input edge; YAML pipeline where the read is used as a non-root step.","solutions":["Use the read transform only as a pipeline source with no input PCollections","If you need Firestore data mid-pipeline, use FirestoreV1.read() transforms or restructure so the read emits into the downstream stage instead of receiving input","Check your SchemaTransform composition/YAML so the read step has no 'input' references"],"exampleFix":"// before\nPCollectionRowTuple.of(\"rows\", existingRows).apply(firestoreReadTransform)\n// after\nPCollectionRowTuple.empty(pipeline).apply(firestoreReadTransform)","handlingStrategy":"validation","validationCode":"if (!input.getAll().isEmpty()) {\n  throw new IllegalArgumentException(\"firestore read transform must be a source: pass an empty PCollectionRowTuple\");\n}","typeGuard":"boolean isSourceUsage(PCollectionRowTuple input) { return input.getAll().isEmpty(); }","tryCatchPattern":"try {\n  PCollectionRowTuple result = input.apply(readTransform);\n} catch (IllegalStateException e) {\n  LOG.error(\"Firestore read got inputs; restructure pipeline so it is the source\", e);\n}","preventionTips":["Read SchemaTransforms are sources — never connect them downstream of another transform","In YAML pipelines keep the read step free of 'input' references","Use FirestoreV1 read transforms for mid-pipeline reads"],"tags":["java","google-cloud-firestore","pipeline-graph"],"backgroundTag":"invalid-state-transition","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"}