apache/beam · error · RuntimeException

@SchemaFieldNumber can only be used on getters in Java Beans

Error message

@SchemaFieldNumber can only be used on getters in Java Beans. Found on setter '%s'

What it means

Thrown by JavaBeanSchema.get when a setter method carries @SchemaFieldNumber. In Java Beans, schema metadata annotations like @SchemaFieldNumber must appear on the getter only; placing it on the setter is rejected to prevent conflicting definitions.

Source

Thrown at sdks/java/core/src/main/java/org/apache/beam/sdk/schemas/JavaBeanSchema.java:119

  /** {@link FieldValueTypeSupplier} that's based on setter methods. */
  @VisibleForTesting
  public static class SetterTypeSupplier implements FieldValueTypeSupplier {
    private static final SetterTypeSupplier INSTANCE = new SetterTypeSupplier();

    @Override
    public List<FieldValueTypeInformation> get(TypeDescriptor<?> typeDescriptor) {
      return ReflectUtils.getMethods(typeDescriptor.getRawType()).stream()
          .filter(ReflectUtils::isSetter)
          .filter(m -> !m.isAnnotationPresent(SchemaIgnore.class))
          .map(m -> FieldValueTypeInformation.forSetter(typeDescriptor, m))
          .map(
              t -> {
                Method m =
                    Preconditions.checkNotNull(
                        t.getMethod(), JavaBeanUtils.SETTER_WITH_NULL_METHOD_ERROR);
                if (m.getAnnotation(SchemaFieldNumber.class) != null) {
                  throw new RuntimeException(
                      String.format(
                          "@SchemaFieldNumber can only be used on getters in Java Beans. Found on"
                              + " setter '%s'",
                          m.getName()));
                }
                if (m.getAnnotation(SchemaFieldName.class) != null) {
                  throw new RuntimeException(
                      String.format(
                          "@SchemaFieldName can only be used on getters in Java Beans. Found on"
                              + " setter '%s'",
                          m.getName()));
                }
                if (m.getAnnotation(SchemaCaseFormat.class) != null) {
                  throw new RuntimeException(
                      String.format(
                          "@SchemaCaseFormat can only be used on getters in Java Beans. Found on"
                              + " setter '%s'",
                          m.getName()));

View on GitHub (pinned to 12126d8942)

Solutions

  1. Move @SchemaFieldNumber from the setter to the corresponding getter.
  2. Remove the annotation from the setter entirely — it is ignored/invalid there by design.

Example fix

// before
@SchemaFieldNumber(0)
public void setName(String name) { ... }

// after
public void setName(String name) { ... }
// (keep @SchemaFieldNumber(0) on getName())
Defensive patterns

Strategy: validation

Validate before calling

for (Method m : clazz.getMethods()) { if (m.getParameterCount() == 1 && m.isAnnotationPresent(SchemaFieldNumber.class)) { throw new IllegalStateException("@SchemaFieldNumber must be on the getter of " + m.getName().substring(3)); } }

Try / catch

try { schemaOf(clazz); } catch (RuntimeException e) { if (e.getMessage().contains("@SchemaFieldNumber can only be used on getters")) { /* move annotation to getter */ } else { throw e; } }

Prevention

When it happens

Trigger: Annotating a setter (e.g. setName) with @SchemaFieldNumber; schema registration then introspects setter methods and throws this exception.

Common situations: Copy-pasting annotations from getters to setters; codegen generating symmetric annotations; misunderstanding that annotations belong on setters.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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