{"record":{"id":"f2a530ceadd2661b","repo":"apache/beam","slug":"unable-to-construct-ontimerfamily-invoker-for-classname","errorCode":null,"errorMessage":"Unable to construct @OnTimerFamily invoker for ${className}","messagePattern":"Unable to construct @OnTimerFamily invoker for (.+?)","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"sdks/java/core/src/main/java/org/apache/beam/sdk/transforms/reflect/ByteBuddyOnTimerInvokerFactory.java","lineNumber":104,"sourceCode":"\n  public <InputT, OutputT> OnTimerInvoker<InputT, OutputT> forTimerFamily(\n      DoFn<InputT, OutputT> fn, String timerId) {\n\n    @SuppressWarnings(\"unchecked\")\n    Class<? extends DoFn<?, ?>> fnClass = (Class<? extends DoFn<?, ?>>) fn.getClass();\n    try {\n      OnTimerMethodSpecifier onTimerMethodSpecifier =\n          OnTimerMethodSpecifier.forClassAndTimerId(fnClass, timerId);\n      Constructor<?> constructor = constructorTimerFamilyCache.get(onTimerMethodSpecifier);\n\n      return (OnTimerInvoker<InputT, OutputT>) constructor.newInstance(fn);\n    } catch (InstantiationException\n        | IllegalAccessException\n        | IllegalArgumentException\n        | InvocationTargetException\n        | SecurityException\n        | ExecutionException e) {\n      throw new RuntimeException(\n          String.format(\n              \"Unable to construct @%s invoker for %s\",\n              DoFn.OnTimerFamily.class.getSimpleName(), fn.getClass().getName()),\n          e);\n    }\n  }\n\n  public static ByteBuddyOnTimerInvokerFactory only() {\n    return INSTANCE;\n  }\n\n  private static final ByteBuddyOnTimerInvokerFactory INSTANCE =\n      new ByteBuddyOnTimerInvokerFactory();\n\n  private ByteBuddyOnTimerInvokerFactory() {}\n\n  /**\n   * The field name for the delegate of {@link DoFn} subclass that a bytebuddy invoker will call.","sourceCodeStart":86,"sourceCodeEnd":122,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/core/src/main/java/org/apache/beam/sdk/transforms/reflect/ByteBuddyOnTimerInvokerFactory.java#L86-L122","documentation":"ByteBuddyOnTimerInvokerFactory.forTimerFamily does for @OnTimerFamily methods what forTimer does for @OnTimer: it generates an invoker class with ByteBuddy and instantiates it reflectively. Failures in generation, classloading, constructor access, or invocation (including the same six checked/reflective exception types) are wrapped in this RuntimeException naming the DoFn class. It indicates the timer-family dispatch machinery could not be built for that DoFn.","triggerScenarios":"Calling forTimerFamily (or triggering a timer family) for a DoFn whose @OnTimerFamily invoker cannot be generated or constructed: inaccessible/non-static DoFn class, ByteBuddy generation failure on the JVM, or reflective instantiation throwing any of the wrapped exception types.","commonSituations":"DoFn with @OnTimerFamily defined as a private or inner class; runners with restrictive classloading (Flink user-code classloader) that cannot see generated classes; newer JDKs unsupported by the bundled ByteBuddy version; missing TimerFamily spec registration in the DoFn signature.","solutions":["Declare the DoFn as a public top-level (or public static nested) class with a visible constructor.","Inspect getCause() of the thrown RuntimeException to pinpoint generation vs instantiation failure.","Upgrade Beam (and its bundled ByteBuddy) or set -Dnet.bytebuddy.experimental=true for new JDK compatibility.","Verify the @OnTimerFamily method's timer family ID matches a @TimerFamily field declaration in the DoFn."],"exampleFix":"// before: private nested class\nprivate class FamilyFn extends DoFn<KV<String,Integer>, String> {\n  @TimerFamily(\"tf\") private final TimerSpec spec = TimerSpecs.timerMap(...);\n  @OnTimerFamily(\"tf\") public void on(Map<String,Timer> ts) {...}\n}\n// after: public static class with public members\npublic static class FamilyFn extends DoFn<KV<String,Integer>, String> {\n  @TimerFamily(\"tf\") public final TimerSpec spec = TimerSpecs.timerMap(...);\n  @OnTimerFamily(\"tf\") public void on(Map<String,Timer> ts) {...}\n}","handlingStrategy":"try-catch","validationCode":"if (!Modifier.isPublic(fn.getClass().getModifiers()) || fn.getClass().isAnonymousClass()) {\n  throw new IllegalStateException(\"@OnTimerFamily DoFn must be public and instantiable\");\n}\nboolean hasFamilyMethod = java.util.Arrays.stream(fn.getClass().getDeclaredMethods())\n    .anyMatch(m -> m.isAnnotationPresent(DoFn.OnTimerFamily.class));\nif (!hasFamilyMethod) throw new IllegalStateException(\"No @OnTimerFamily method on \" + fn.getClass());","typeGuard":null,"tryCatchPattern":"try {\n  invoker = ByteBuddyOnTimerInvokerFactory.forTimerFamily(fn, timerFamilyId);\n} catch (RuntimeException e) {\n  log.error(\"@OnTimerFamily invoker construction failed for \" + fn.getClass().getName()\n      + \"; cause=\" + e.getCause(), e);\n  throw e;\n}","preventionTips":["Use public top-level/static DoFn classes with accessible constructors","Ensure @OnTimerFamily IDs match declared @TimerFamily specs","Validate timer-family pipelines under the production runner's classloader settings in CI","Align Beam/ByteBuddy versions with the JDK used at runtime"],"tags":["java","reflection","bytecode","timers","apache-beam"],"backgroundTag":"class-not-found","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}