{"record":{"id":"01b9f4486fbce479","repo":"apache/beam","slug":"metadata-instance-can-not-be-null","errorCode":null,"errorMessage":"Metadata instance can not be null","messagePattern":"Metadata instance can not be null","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"sdks/java/io/google-cloud-platform/src/main/java/org/apache/beam/sdk/io/gcp/spanner/changestreams/dao/DaoFactory.java","lineNumber":83,"sourceCode":"   * @param metadataSpannerConfig the metadata tables configuration\n   * @param partitionMetadataTableNames the names of the partition metadata ddl objects\n   * @param tvfNameList the list of TVF names specified to query and union\n   * @param rpcPriority the priority of the requests made by the DAO queries\n   * @param jobName the name of the running job\n   */\n  public DaoFactory(\n      SpannerConfig changeStreamSpannerConfig,\n      String changeStreamName,\n      List<String> tvfNameList,\n      SpannerConfig metadataSpannerConfig,\n      PartitionMetadataTableNames partitionMetadataTableNames,\n      RpcPriority rpcPriority,\n      String jobName,\n      Dialect spannerChangeStreamDatabaseDialect,\n      Dialect metadataDatabaseDialect,\n      boolean isMutableChangeStream) {\n    if (metadataSpannerConfig.getInstanceId() == null) {\n      throw new IllegalArgumentException(\"Metadata instance can not be null\");\n    }\n    if (metadataSpannerConfig.getDatabaseId() == null) {\n      throw new IllegalArgumentException(\"Metadata database can not be null\");\n    }\n    this.changeStreamSpannerConfig = changeStreamSpannerConfig;\n    this.changeStreamName = changeStreamName;\n    this.tvfNameList =\n        tvfNameList == null ? ChangeStreamsConstants.DEFAULT_TVF_NAME_LIST : tvfNameList;\n    this.metadataSpannerConfig = metadataSpannerConfig;\n    this.partitionMetadataTableNames = partitionMetadataTableNames;\n    this.rpcPriority = rpcPriority;\n    this.jobName = jobName;\n    this.spannerChangeStreamDatabaseDialect = spannerChangeStreamDatabaseDialect;\n    this.metadataDatabaseDialect = metadataDatabaseDialect;\n    this.isMutableChangeStream = isMutableChangeStream;\n  }\n\n  /** Returns the tvf name list. */","sourceCodeStart":65,"sourceCodeEnd":101,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/io/google-cloud-platform/src/main/java/org/apache/beam/sdk/io/gcp/spanner/changestreams/dao/DaoFactory.java#L65-L101","documentation":"DaoFactory's constructor validates the metadata Spanner configuration before building DAOs. If metadataSpannerConfig has no instanceId, it immediately throws IllegalArgumentException because change stream metadata cannot be stored without a Spanner instance.","triggerScenarios":"Constructing DaoFactory (e.g. from SpannerChangestreamsReadSchemaTransformProvider expansion) with a metadata configuration whose instanceId was never set — typically a SpannerConfig built with only projectId/databaseId.","commonSituations":"Users configuring the change stream read with only the source database settings and forgetting the separate metadata instance/database options; programmatic config building where setMetadataInstance() was skipped.","solutions":["Set the metadata instance on the config, e.g. withMetadataInstance(\"my-instance\") on the SpannerChangeStreamReadSchemaTransformConfiguration.","If metadata should live in the same instance as the source database, explicitly copy that instance id into the metadata config.","Check how the SpannerConfig is constructed programmatically and ensure instanceId is non-null before calling new DaoFactory(...)."],"exampleFix":"// before\nSpannerConfig metaConfig = SpannerConfig.builder().setProjectId(\"p\").setDatabaseId(\"meta-db\").build();\n// after\nSpannerConfig metaConfig = SpannerConfig.builder().setProjectId(\"p\").setInstanceId(\"my-instance\").setDatabaseId(\"meta-db\").build();","handlingStrategy":"validation","validationCode":"if (metadataSpannerConfig.getInstanceId() == null) {\n  throw new IllegalArgumentException(\"Set withMetadataInstance() before expansion\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always set both metadata instance and database in the transform configuration.","Add a config precheck that fails fast before job submission.","Default metadata to the source instance/database explicitly when that is intended."],"tags":["spanner","config-validation","null","java"],"backgroundTag":"missing-required-config-field","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"}