apache/beam · error · RuntimeException

Unable to generate a setter for setter '%s'

Error message

Unable to generate a setter for setter '%s'

What it means

JavaBeanUtils.generateSetters builds dynamic FieldValueSetter implementations for a Java bean's getter/setter methods via bytecode generation (ByteBuddy). When instantiating the generated setter class fails — because the reflective constructor invocation threw InstantiationException, IllegalAccessException, NoSuchMethodException, or InvocationTargetException — this RuntimeException wraps the failure. It means the schema-derived setter method could not be made callable for the target type.

Source

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

            BYTE_BUDDY,
            m.getDeclaringClass(),
            typeConversionsFactory.createTypeConversion(false).convert(typeInformation.getType()));
    builder = implementSetterMethods(builder, typeInformation, typeConversionsFactory);
    try {
      return builder
          .visit(new AsmVisitorWrapper.ForDeclaredMethods().writerFlags(ClassWriter.COMPUTE_FRAMES))
          .make()
          .load(
              ReflectHelpers.findClassLoader(m.getDeclaringClass().getClassLoader()),
              getClassLoadingStrategy(m.getDeclaringClass()))
          .getLoaded()
          .getDeclaredConstructor()
          .newInstance();
    } catch (InstantiationException
        | IllegalAccessException
        | NoSuchMethodException
        | InvocationTargetException e) {
      throw new RuntimeException(
          "Unable to generate a setter for setter '" + typeInformation.getMethod() + "'");
    }
  }

  private static <ObjectT, ValueT>
      DynamicType.Builder<FieldValueSetter<ObjectT, ValueT>> implementSetterMethods(
          DynamicType.Builder<FieldValueSetter<ObjectT, ValueT>> builder,
          FieldValueTypeInformation fieldValueTypeInformation,
          TypeConversionsFactory typeConversionsFactory) {
    return builder
        .method(ElementMatchers.named("name"))
        .intercept(FixedValue.reference(fieldValueTypeInformation.getName()))
        .method(ElementMatchers.named("set"))
        .intercept(new InvokeSetterInstruction(fieldValueTypeInformation, typeConversionsFactory));
  }

  public static <ObjectT> FieldValueHaver<ObjectT> createHaver(
      Class<ObjectT> clazz, Method hasMethod) {

View on GitHub (pinned to 12126d8942)

Solutions

  1. Give the bean class a public no-arg constructor and make the setter a concrete public method
  2. Verify the class is concrete (not abstract/interface) and publicly accessible
  3. Check the chained cause (or the method name in the message) to see which reflective step failed
  4. Ensure the class is loadable from the classloader Beam uses (same jar/classpath)

Example fix

// before
public class MyBean {
  private MyBean() {}
  public void setName(String name) { ... }
}
// after
public class MyBean {
  public MyBean() {}
  public void setName(String name) { ... }
}
Defensive patterns

Strategy: validation

Validate before calling

static void checkBeanSetter(Class<?> c) throws ReflectiveOperationException {
  if (java.lang.reflect.Modifier.isAbstract(c.getModifiers()))
    throw new IllegalArgumentException(c + " must be concrete");
  c.getDeclaredConstructor(); // throws NoSuchMethodException if no no-arg ctor
  if (!java.lang.reflect.Modifier.isPublic(c.getModifiers()))
    throw new IllegalArgumentException(c + " must be public");
}

Type guard

static boolean isInstantiableBean(Class<?> c) {
  return !c.isInterface() && !java.lang.reflect.Modifier.isAbstract(c.getModifiers())
      && java.lang.reflect.Modifier.isPublic(c.getModifiers())
      && java.util.Arrays.stream(c.getDeclaredConstructors())
          .anyMatch(k -> k.getParameterCount() == 0);
}

Try / catch

try {
  setters = JavaBeanUtils.getSetters(MyBean.class, schema, options);
} catch (RuntimeException e) {
  throw new IllegalStateException("Bean setter generation failed for " + MyBean.class
      + ": " + e.getMessage(), e);
}

Prevention

When it happens

Trigger: Calling JavaBeanUtils.getSetters/createSetter for a JavaBean whose setter method is abstract, non-public, throws in its constructor, or whose declaring class lacks an accessible no-arg constructor, so the generated proxy's getDeclaredConstructor().newInstance() fails.

Common situations: Registering a JavaBean class with a private or missing no-arg constructor as a Beam schema type; bean setters declared in an interface or abstract class; a classloader/visibility issue (package-private bean in another package) breaking reflective access.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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