{"record":{"id":"71736b1b1bd9be41","repo":"apache/beam","slug":"createrowwriter-called-when-dynamicdestinations-is-null","errorCode":null,"errorMessage":"createRowWriter called when dynamicDestinations is null; forgot to call prepare()?","messagePattern":"createRowWriter called when dynamicDestinations is null; forgot to call prepare\\(\\)\\?","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"sdks/java/io/google-cloud-platform/src/main/java/org/apache/beam/sdk/io/gcp/bigquery/RowWriterFactory.java","lineNumber":134,"sourceCode":"        DynamicDestinations<?, DestinationT> dynamicDestinations,\n        SerializableFunction<@Nullable TableSchema, Schema> schemaFactory) {\n      return new AvroRowWriterFactory<>(toAvro, writerFactory, schemaFactory, dynamicDestinations);\n    }\n\n    SerializableFunction<AvroWriteRequest<ElementT>, AvroT> getToAvroFn() {\n      return toAvro;\n    }\n\n    @Override\n    OutputType getOutputType() {\n      return OutputType.AvroGenericRecord;\n    }\n\n    @Override\n    BigQueryRowWriter<ElementT> createRowWriter(String tempFilePrefix, DestinationT destination)\n        throws Exception {\n      if (dynamicDestinations == null) {\n        throw new IllegalStateException(\n            \"createRowWriter called when dynamicDestinations is null; forgot to call prepare()?\");\n      }\n      if (schemaFactory == null) {\n        throw new IllegalStateException(\n            \"createRowWriter called when schemaFactory is null; forgot to call prepare()?\");\n      }\n\n      TableSchema tableSchema = dynamicDestinations.getSchema(destination);\n      Schema avroSchema = schemaFactory.apply(tableSchema);\n      return new AvroRowWriter<>(tempFilePrefix, avroSchema, toAvro, writerFactory);\n    }\n\n    @Override\n    String getSourceFormat() {\n      return \"AVRO\";\n    }\n  }\n}","sourceCodeStart":116,"sourceCodeEnd":152,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/io/google-cloud-platform/src/main/java/org/apache/beam/sdk/io/gcp/bigquery/RowWriterFactory.java#L116-L152","documentation":"IllegalStateException thrown by RowWriterFactory's anonymous Avro implementation when createRowWriter is invoked but the dynamicDestinations field is null. The factory's prepare() lifecycle method is what initializes dynamicDestinations, so a null field indicates the DoFn was used without its setup being run (or it was constructed incorrectly).","triggerScenarios":"Calling createRowWriter (directly or via a BigQueryIO write) on a RowWriterFactory whose prepare(GenericRecordWriterFactory, DynamicDestinations) was never invoked, e.g. by manually instantiating the factory and skipping pipeline setup.","commonSituations":"Custom DoFns or unit tests that construct RowWriterFactory directly and call createRowWriter without first calling prepare(); refactors that moved writer creation outside the normal @Setup/@StartBundle lifecycle; misuse of the BigQueryIO internal API.","solutions":["Ensure prepare(...) is called on the factory before any createRowWriter call","If driving the DoFn manually (tests), simulate the full lifecycle: construct, call prepare with the writer factory and dynamic destinations, then createRowWriter","Avoid constructing RowWriterFactory subclasses directly; build the write via BigQueryIO.write() so Beam manages the lifecycle"],"exampleFix":"// before\nRowWriterFactory<String, TableDestination> factory = new AvroFactory<>(toAvro, writerFactory);\nfactory.createRowWriter(prefix, destination); // IllegalStateException\n// after\nfactory.prepare(writerFactory, dynamicDestinations);\nfactory.createRowWriter(prefix, destination);","handlingStrategy":"validation","validationCode":"if (factory == null || factory.hasDynamicDestinations() == false /* or assert initialized */) {\n  throw new IllegalStateException(\"Call prepare() before createRowWriter()\");\n}","typeGuard":"static <E,D> boolean isPrepared(RowWriterFactory<E,D> f) {\n  try { return f.getClass().getDeclaredField(\"dynamicDestinations\").get(f) != null; }\n  catch (Exception e) { return false; }\n}","tryCatchPattern":"try {\n  writer = factory.createRowWriter(prefix, destination);\n} catch (IllegalStateException e) {\n  if (e.getMessage().contains(\"dynamicDestinations is null\")) {\n    factory.prepare(writerFactory, dynamicDestinations);\n    writer = factory.createRowWriter(prefix, destination);\n  } else { throw e; }\n}","preventionTips":["Always call prepare() immediately after constructing RowWriterFactory","In tests, replicate the DoFn lifecycle: construct -> prepare -> createRowWriter","Prefer building writes via BigQueryIO.write() so Beam manages initialization"],"tags":["bigquery","lifecycle","state","gcp"],"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"}