apache/beam · error · RuntimeException

Unexpected null schema!

Error message

Unexpected null schema!

What it means

fieldDescriptorFromBeamField, when handling a ROW-typed Beam field, calls field.getType().getRowSchema() and throws "Unexpected null schema!" if it returns null. A ROW FieldType must always carry a nested Schema; a null result means the field type was constructed without one, so nested TableFieldSchema fields can't be derived.

Solutions

  1. Attach the nested schema: Schema.FieldType.row(nestedSchema) instead of a bare ROW type
  2. Verify every ROW field in your Schema has a non-null row schema before writing
  3. Check the code path that constructs your Schema (e.g. from a POJO) to ensure nested objects are registered
  4. Rebuild nested fields with Schema.builder().add... to guarantee a complete schema

Example fix

// before
Schema.FieldType rowType = Schema.FieldType.row(null); // or bare ROW
// after
Schema.FieldType rowType = Schema.FieldType.row(nestedSchema);
Defensive patterns

Strategy: validation

Validate before calling

// Java
for (Schema.Field f : beamSchema.getFields()) {
  if (f.getType().getTypeName() == TypeName.ROW && f.getType().getRowSchema() == null) {
    throw new IllegalStateException("ROW field without nested schema: " + f.getName());
  }
}

Type guard

// Java
Schema nested = fieldType.getRowSchema();
if (nested != null) { /* safe to recurse */ }

Try / catch

// Java
try {
  descriptor = BeamRowToStorageApiProto.protoTableSchemaFromBeamSchema(beamSchema);
} catch (RuntimeException e) {
  if (e.getMessage().equals("Unexpected null schema!")) {
    // rebuild the schema attaching nested row schemas
  }
  throw e;
}

Prevention

When it happens

Trigger: Building a Beam Schema field with Schema.FieldType.row(null) or a FieldType incorrectly typed as ROW without attaching the nested schema, then writing via BigQueryIO Storage API

Common situations: Reflection/inference-based schema builders producing ROW fields without schemas; custom FieldType factories; deserialized schemas missing nested definitions.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of apache/beam@12126d8942 (2026-09-13). Data as JSON: /api/errors/fc73f793a385520f. Report an issue: GitHub.

Appendix: source

Thrown at sdks/java/io/google-cloud-platform/src/main/java/org/apache/beam/sdk/io/gcp/bigquery/BeamRowToStorageApiProto.java:214

    TableSchema.Builder builder = TableSchema.newBuilder();
    for (Field field : schema.getFields()) {
      builder.addFields(fieldDescriptorFromBeamField(field));
    }
    return builder.build();
  }

  private static TableFieldSchema fieldDescriptorFromBeamField(Field field) {
    TableFieldSchema.Builder builder = TableFieldSchema.newBuilder();
    if (StorageApiCDC.COLUMNS.contains(field.getName())) {
      throw new RuntimeException("Reserved field name " + field.getName() + " in user schema.");
    }
    builder = builder.setName(field.getName().toLowerCase());

    switch (field.getType().getTypeName()) {
      case ROW:
        @Nullable Schema rowSchema = field.getType().getRowSchema();
        if (rowSchema == null) {
          throw new RuntimeException("Unexpected null schema!");
        }
        builder = builder.setType(TableFieldSchema.Type.STRUCT);
        for (Schema.Field nestedField : rowSchema.getFields()) {
          builder = builder.addFields(fieldDescriptorFromBeamField(nestedField));
        }
        break;
      case ARRAY:
      case ITERABLE:
        @Nullable FieldType elementType = field.getType().getCollectionElementType();
        if (elementType == null) {
          throw new RuntimeException("Unexpected null element type on " + field.getName());
        }
        TypeName containedTypeName =
            Preconditions.checkNotNull(
                elementType.getTypeName(),
                "Null type name found in contained type at %s",
                field.getName());
        Preconditions.checkState(

View on GitHub (pinned to 12126d8942)