{"record":{"id":"60b670b6f96efebd","repo":"apache/beam","slug":"was-not-able-to-generate-getters-for-schema-class","errorCode":null,"errorMessage":"Was not able to generate getters for schema: {} class: {}","messagePattern":"Was not able to generate getters for schema: (.+?) class: (.+?)","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"sdks/java/core/src/main/java/org/apache/beam/sdk/schemas/utils/POJOUtils.java","lineNumber":120,"sourceCode":"  public static <T> List<FieldValueGetter<@NonNull T, Object>> getGetters(\n      TypeDescriptor<T> typeDescriptor,\n      Schema schema,\n      FieldValueTypeSupplier fieldValueTypeSupplier,\n      TypeConversionsFactory typeConversionsFactory) {\n    // Return the getters ordered by their position in the schema.\n    return (List)\n        CACHED_GETTERS.computeIfAbsent(\n            TypeDescriptorWithSchema.create(typeDescriptor, schema),\n            c -> {\n              List<FieldValueTypeInformation> types =\n                  fieldValueTypeSupplier.get(typeDescriptor, schema);\n              List<FieldValueGetter<@NonNull T, Object>> getters =\n                  types.stream()\n                      .<FieldValueGetter<@NonNull T, Object>>map(\n                          t -> POJOUtils.createGetter(t, typeConversionsFactory))\n                      .collect(Collectors.toList());\n              if (getters.size() != schema.getFieldCount()) {\n                throw new RuntimeException(\n                    \"Was not able to generate getters for schema: \"\n                        + schema\n                        + \" class: \"\n                        + typeDescriptor);\n              }\n              return (List) getters;\n            });\n  }\n\n  // The list of constructors for a class is cached, so we only create the classes the first time\n  // getConstructor is called.\n  public static final Map<TypeDescriptorWithSchema<?>, SchemaUserTypeCreator> CACHED_CREATORS =\n      Maps.newConcurrentMap();\n\n  public static <T> SchemaUserTypeCreator getSetFieldCreator(\n      TypeDescriptor<T> typeDescriptor,\n      Schema schema,\n      FieldValueTypeSupplier fieldValueTypeSupplier,","sourceCodeStart":102,"sourceCodeEnd":138,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/core/src/main/java/org/apache/beam/sdk/schemas/utils/POJOUtils.java#L102-L138","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Regenerate the schema from the current POJO (POJOUtils.schemaFromType / Schema inference) so field count matches the class.","Ensure the same class version and classpath are used at pipeline construction and at runtime (fat jar / staging consistency).","Check whether multiple mapped types (types.stream()) legitimately yield more getters than schema fields; align @SchemaFieldNumber/name annotations with the schema.","Use SchemaCoder/serialization consistency: clear any stale cached schema and rebuild the coder."],"exampleFix":"// before\nSchema schema = Schema.builder().addInt32Field(\"a\").build(); // stale: POJO now has 'a' and 'b'\nList<FieldValueGetter<T, Object>> getters = POJOUtils.getGetters(TypeDescriptor.of(MyPojo.class), schema, factory);\n// after\nSchema schema = POJOUtils.schemaFromType(TypeDescriptor.of(MyPojo.class)); // inferred from current class","handlingStrategy":"validation","validationCode":"Schema inferred = POJOUtils.schemaFromType(TypeDescriptor.of(MyPojo.class));\nif (!inferred.equivalent(schema)) {\n  throw new IllegalStateException(\"Registered schema stale: expected \" + inferred + \" got \" + schema);\n}","typeGuard":null,"tryCatchPattern":"try {\n  List<FieldValueGetter<T, Object>> getters = POJOUtils.getGetters(td, schema, factory);\n} catch (RuntimeException e) {\n  if (e.getMessage() != null && e.getMessage().startsWith(\"Was not able to generate getters\")) {\n    schema = POJOUtils.schemaFromType(td); // re-infer and retry once\n  } else throw e;\n}","preventionTips":["Always infer the schema from the live class instead of caching it across deploys.","Keep the POJO classpath identical between job submission and workers.","Use @SchemaFieldNumber/@SchemaFieldDefault annotations so field order/count is stable."],"tags":["java","beam-schema","pojo","reflection"],"backgroundTag":"schema-validation-failed","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}