apache/beam · error · RuntimeException

Was not able to generate getters for schema

Error message

Was not able to generate getters for schema: {} class: {}

What it means

POJOUtils.getGetters generates runtime getter classes for a POJO matching its inferred schema. After generating one getter per resolved type it validates the count against schema.getFieldCount(); if the number of generated getters does not match the schema's field count, it throws this RuntimeException, meaning schema inference and reflection disagreed.

Solutions

  1. Regenerate the schema from the current POJO (POJOUtils.schemaFromType / Schema inference) so field count matches the class.
  2. Ensure the same class version and classpath are used at pipeline construction and at runtime (fat jar / staging consistency).
  3. Check whether multiple mapped types (types.stream()) legitimately yield more getters than schema fields; align @SchemaFieldNumber/name annotations with the schema.
  4. Use SchemaCoder/serialization consistency: clear any stale cached schema and rebuild the coder.

Example fix

// before
Schema schema = Schema.builder().addInt32Field("a").build(); // stale: POJO now has 'a' and 'b'
List<FieldValueGetter<T, Object>> getters = POJOUtils.getGetters(TypeDescriptor.of(MyPojo.class), schema, factory);
// after
Schema schema = POJOUtils.schemaFromType(TypeDescriptor.of(MyPojo.class)); // inferred from current class
Defensive patterns

Strategy: validation

Validate before calling

Schema inferred = POJOUtils.schemaFromType(TypeDescriptor.of(MyPojo.class));
if (!inferred.equivalent(schema)) {
  throw new IllegalStateException("Registered schema stale: expected " + inferred + " got " + schema);
}

Try / catch

try {
  List<FieldValueGetter<T, Object>> getters = POJOUtils.getGetters(td, schema, factory);
} catch (RuntimeException e) {
  if (e.getMessage() != null && e.getMessage().startsWith("Was not able to generate getters")) {
    schema = POJOUtils.schemaFromType(td); // re-infer and retry once
  } else throw e;
}

Prevention

When it happens

Trigger: Calling getGetters(typeDescriptor, schema, typeConversionsFactory) when the schema was produced for a different class version (fields added/removed between inference and use), when field name-case normalization collapses distinct fields, or when the passed schema does not correspond to typeDescriptor.

Common situations: Schema registered/cached from an older POJO version (serialization by Schemas at pipeline submit vs runtime classpath mismatch), heterogeneous subclasses in a union being flattened, or manually built schemas missing/extra fields.

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/60b670b6f96efebd. Report an issue: GitHub.

Appendix: source

Thrown at sdks/java/core/src/main/java/org/apache/beam/sdk/schemas/utils/POJOUtils.java:120

  public static <T> List<FieldValueGetter<@NonNull T, Object>> getGetters(
      TypeDescriptor<T> typeDescriptor,
      Schema schema,
      FieldValueTypeSupplier fieldValueTypeSupplier,
      TypeConversionsFactory typeConversionsFactory) {
    // Return the getters ordered by their position in the schema.
    return (List)
        CACHED_GETTERS.computeIfAbsent(
            TypeDescriptorWithSchema.create(typeDescriptor, schema),
            c -> {
              List<FieldValueTypeInformation> types =
                  fieldValueTypeSupplier.get(typeDescriptor, schema);
              List<FieldValueGetter<@NonNull T, Object>> getters =
                  types.stream()
                      .<FieldValueGetter<@NonNull T, Object>>map(
                          t -> POJOUtils.createGetter(t, typeConversionsFactory))
                      .collect(Collectors.toList());
              if (getters.size() != schema.getFieldCount()) {
                throw new RuntimeException(
                    "Was not able to generate getters for schema: "
                        + schema
                        + " class: "
                        + typeDescriptor);
              }
              return (List) getters;
            });
  }

  // The list of constructors for a class is cached, so we only create the classes the first time
  // getConstructor is called.
  public static final Map<TypeDescriptorWithSchema<?>, SchemaUserTypeCreator> CACHED_CREATORS =
      Maps.newConcurrentMap();

  public static <T> SchemaUserTypeCreator getSetFieldCreator(
      TypeDescriptor<T> typeDescriptor,
      Schema schema,
      FieldValueTypeSupplier fieldValueTypeSupplier,

View on GitHub (pinned to 12126d8942)