{"record":{"id":"d53fd36a3304cce5","repo":"apache/beam","slug":"timerfamily-unsupported-in-context","errorCode":null,"errorMessage":"TimerFamily unsupported in ${context}","messagePattern":"TimerFamily unsupported in (.+?)","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"sdks/java/core/src/main/java/org/apache/beam/sdk/transforms/reflect/DoFnInvoker.java","lineNumber":330,"sourceCode":"      throw new UnsupportedOperationException(\n          String.format(\"Element unsupported in %s\", getErrorContext()));\n    }\n\n    @Override\n    public @Nullable Object key() {\n      throw new UnsupportedOperationException(\n          \"Cannot access key as parameter outside of @OnTimer method.\");\n    }\n\n    @Override\n    public @Nullable Object sideInput(String tagId) {\n      throw new UnsupportedOperationException(\n          String.format(\"SideInput unsupported in %s\", getErrorContext()));\n    }\n\n    @Override\n    public TimerMap timerFamily(String tagId) {\n      throw new UnsupportedOperationException(\n          String.format(\"TimerFamily unsupported in %s\", getErrorContext()));\n    }\n\n    @Override\n    public @Nullable Object schemaElement(int index) {\n      throw new UnsupportedOperationException(\n          String.format(\"Schema element unsupported in %s\", getErrorContext()));\n    }\n\n    @Override\n    public Instant timestamp(DoFn<InputT, OutputT> doFn) {\n      throw new UnsupportedOperationException(\n          String.format(\"Timestamp unsupported in %s\", getErrorContext()));\n    }\n\n    @Override\n    public @Nullable String currentRecordId(DoFn<InputT, OutputT> doFn) {\n      throw new UnsupportedOperationException(","sourceCodeStart":312,"sourceCodeEnd":348,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/core/src/main/java/org/apache/beam/sdk/transforms/reflect/DoFnInvoker.java#L312-L348","documentation":"This UnsupportedOperationException is thrown by DoFnInvoker.BaseArgumentProvider.timerFamily when a timer-family parameter is requested in a DoFn invocation context that cannot supply one. Timer families (DoFn.TimerMap / @TimerFamily) only exist while an @OnTimer method is firing, so every other context's ArgumentProvider leaves timerFamily un-overridden and inherits this throwing default. The context name is filled in by getErrorContext() so the developer can see where the illegal access happened.","triggerScenarios":"Requesting a TimerMap (e.g. c.timerFamily(\"family\") or an @TimerFamily annotated parameter) from a context other than a firing timer: @ProcessElement, @StartBundle, @FinishBundle, @OnWindowExpiration methods, or custom ArgumentProviders that do not override timerFamily(String).","commonSituations":"Trying to set/reset timers from @ProcessElement via timerFamily instead of the per-timer c.timer(...) API; declaring a TimerMap parameter on a non-@OnTimer method and letting the invoker bind it; SDK/runner mismatch where the runner's ArgumentProvider does not yet support TimerFamily (older runners or Flink/Spark versions predating timer families).","solutions":["Only request a TimerMap inside @OnTimer methods; in @ProcessElement use DoFn.ProcessContext.timer(timerId) for individual timers instead.","Verify the parameter's annotation/context matches the method it is declared on (e.g. @TimerFamily parameters belong on @OnTimer methods).","Check the runner's support level for timer families (RunnerDAG capability) and upgrade the runner/SDK if TimerFamily is not yet supported.","If implementing a custom ArgumentProvider, override timerFamily(String) to return the actual TimerMap for the firing context."],"exampleFix":"// before\n@ProcessElement\npublic void processElement(ProcessContext c) {\n  c.timerFamily(\"cleanup\").set(c.timestamp().plus(Duration.standardMinutes(5))); // throws\n}\n\n// after\n@ProcessElement\npublic void processElement(ProcessContext c) {\n  c.timer(\"cleanup\").set(c.timestamp().plus(Duration.standardMinutes(5)));\n}","handlingStrategy":"validation","validationCode":"// TimerMap parameters are only valid on @OnTimer methods; check before building the pipeline.\nDoFnSignature sig = DoFnSignatures.getSignature(doFn.getClass());\nsig.timerFamilyDeclarations(); // ensure each declaration's receiver is an OnTimerContext method","typeGuard":"if (context instanceof DoFn.OnTimerContext) {\n  // timer family access is only meaningful here\n}","tryCatchPattern":"try {\n  TimerMap timers = context.timerFamily(\"cleanup\");\n} catch (UnsupportedOperationException e) {\n  // not a timer-firing context; schedule timers via ProcessContext.timer() instead\n}","preventionTips":["Use c.timer(timerId) from @ProcessElement; reserve TimerMap for @OnTimer.","Confirm runner support for timer families before using @TimerFamily.","Keep @TimerFamily parameters only on methods annotated @OnTimer."],"tags":["apache-beam","java","unsupported-operation","timers","dofn"],"backgroundTag":"unsupported-operation","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"}