apache/beam · error · java.lang.IllegalArgumentException

%s is not nullable in Array field %s

Error message

%s is not nullable in Array field %s

What it means

Beam Row schemas can declare whether array/iterable elements are nullable. When capturing an iterable field, a null element was found although the element type is declared non-nullable, so captureIterable throws IllegalArgumentException. Note: the top-level collection itself may be null per its own nullability, but individual elements must respect the element type's nullable flag.

Source

Thrown at sdks/java/core/src/main/java/org/apache/beam/sdk/values/RowUtils.java:485

      }
      return retValue;
    }

    private Collection<Object> captureIterable(
        RowPosition rowPosition,
        FieldType collectionElementType,
        Iterable<Object> values,
        RowFieldMatcher matcher) {
      if (values == null) {
        return null;
      }

      List<Object> captured = Lists.newArrayListWithCapacity(Iterables.size(values));
      RowPosition elementPosition = rowPosition.withArrayQualifier();
      for (Object listValue : values) {
        if (listValue == null) {
          if (!collectionElementType.getNullable()) {
            throw new IllegalArgumentException(
                String.format(
                    "%s is not nullable in Array field %s",
                    collectionElementType, rowPosition.descriptor));
          }
          captured.add(null);
        } else {
          Object capturedElement =
              matcher.match(this, collectionElementType, elementPosition, listValue);
          captured.add(capturedElement);
        }
      }
      return captured;
    }

    @Override
    public Map<Object, Object> processMap(
        RowPosition rowPosition,
        FieldType keyType,

View on GitHub (pinned to 12126d8942)

Solutions

  1. Declare array elements nullable: Schema.FieldType.array(Schema.FieldType.STRING.withNullable(true))
  2. Filter or replace null elements before building the Row (e.g. lists.transform, Iterables.filter(Objects::nonNull))
  3. Fix the data-producing step so null elements never enter the collection

Example fix

// before
List<String> tags = Arrays.asList("a", null);
// after
List<String> tags = Streams.stream(rawTags).filter(Objects::nonNull).collect(Collectors.toList());
Defensive patterns

Strategy: validation

Validate before calling

if (list.contains(null) && !elementType.getNullable()) {
  list = list.stream().filter(Objects::nonNull).collect(Collectors.toList());
}

Prevention

When it happens

Trigger: RowUtils.captureIterable (called from processArray/processIterable during schema attach/match) iterating values and hitting a null element while collectionElementType.getNullable() is false.

Common situations: Lists built from data with missing entries (e.g. Arrays.asList("a", null)); deserialized data that predates a nullability change; building Rows from joins/lookups that return null elements.

Related errors


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