apache/beam · error · IllegalArgumentException

Expected Row for nested field.

Error message

Expected Row for nested field.

What it means

When javaToValue converts a ROW-typed field, the actual Java value must be an instance of Beam's Row class so its fields can be read and serialized to a Firestore MapValue. If the value is any other object (or null handled elsewhere), the type contract is broken and it throws IllegalArgumentException('Expected Row for nested field.').

Solutions

  1. Wrap nested data in a Row created with the same nested schema before writing
  2. Convert Maps/POJOs to Row via Row.withSchema(nestedSchema).attachValues(...) or rowFromMap-style helpers
  3. Align the field's FieldType.row(schema) with the actual value type produced upstream

Example fix

// before
Row row = Row.withSchema(schema).addValues(new HashMap<>(nestedMap)).build(); // Map in ROW slot
// after
Row nested = Row.withSchema(nestedSchema).attachValues("a", 1);
Row row = Row.withSchema(schema).addValues(nested).build();
Defensive patterns

Strategy: type-guard

Validate before calling

Object v = row.getValue("nestedField");
if (v != null && !(v instanceof Row)) {
  throw new IllegalStateException("nestedField must be a Row, got " + v.getClass());
}

Type guard

static boolean isNestedRow(Object v) { return v instanceof Row; }

Try / catch

try {
  Document doc = FirestoreUtils.rowToDocument(row, projectId, databaseId, collectionId, idField);
} catch (IllegalArgumentException e) {
  if (e.getMessage().contains("Expected Row for nested field")) {
    log.error("Nested field is not a Row in: {}", row); 
  }
  throw e;
}

Prevention

When it happens

Trigger: Supplying a Map, POJO, or JSON object for a field declared ROW in the schema when writing Rows to Firestore; schema and data built by different code paths that disagree on representation.

Common situations: Passing HashMap instead of Row for a nested record; a transform upstream that decoded JSON into a Map and inserted it into the Row; using generic row getValue with the wrong field index.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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

Appendix: source

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

        }
        for (Map.Entry<?, ?> entry : ((Map<?, ?>) value).entrySet()) {
          Object mapValue = entry.getValue();
          mapBuilder.putFields(
              String.valueOf(entry.getKey()),
              mapValue == null
                  ? Value.newBuilder()
                      .setNullValue(com.google.protobuf.NullValue.NULL_VALUE)
                      .build()
                  : javaToValue(mapValue, valueType));
        }
        return Value.newBuilder().setMapValue(mapBuilder.build()).build();
      case ROW:
        Schema rowSchema = fieldType.getRowSchema();
        if (rowSchema == null) {
          throw new IllegalArgumentException("Row schema cannot be null.");
        }
        if (!(value instanceof Row)) {
          throw new IllegalArgumentException("Expected Row for nested field.");
        }
        MapValue.Builder nestedMapBuilder = MapValue.newBuilder();
        Row nestedRow = (Row) value;
        for (Field nestedField : rowSchema.getFields()) {
          Object nestedValue = nestedRow.getValue(nestedField.getName());
          if (nestedValue != null) {
            nestedMapBuilder.putFields(
                nestedField.getName(), javaToValue(nestedValue, nestedField.getType()));
          }
        }
        return Value.newBuilder().setMapValue(nestedMapBuilder.build()).build();
      default:
        throw new IllegalArgumentException("Unsupported field type: " + fieldType);
    }
  }

  private static @Nullable Object convertFromJava(@Nullable Object value, FieldType fieldType) {
    if (value == null) {

View on GitHub (pinned to 12126d8942)