{"record":{"id":"99848e3d76c3eb5e","repo":"apache/beam","slug":"processelement-doesn-t-use-a-timerprovider-but-timer-field","errorCode":null,"errorMessage":"ProcessElement doesn't use a TimerProvider, but Timer field is attached to the DoFn: %v, Ensure that you are using the TimerProvider to set and clear the timers.","messagePattern":"ProcessElement doesn't use a TimerProvider, but Timer field is attached to the DoFn: (.+?), Ensure that you are using the TimerProvider to set and clear the timers\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"sdks/go/pkg/beam/core/graph/fn.go","lineNumber":1448,"sourceCode":"\t\t\treturn errors.SetTopLevelMsgf(err, \"ProcessElement uses a TimerProvider, but no timer fields are defined in the DoFn\"+\n\t\t\t\t\", Ensure that your DoFn exports the Timer fields used to set and clear timers.\")\n\t\t}\n\t\ttimerKeys := make(map[string]string)\n\t\tfor i, t := range pt {\n\t\t\tfor timerFamilyID := range t.Timers() {\n\t\t\t\tif timer, ok := timerKeys[timerFamilyID]; ok {\n\t\t\t\t\terr := errors.Errorf(\"Duplicate timer key %v\", timerFamilyID)\n\t\t\t\t\treturn errors.SetTopLevelMsgf(err, \"Duplicate timer family ID %v used by struct fields %v and %v. Ensure that timer family IDs are unique per DoFn\", timerFamilyID, timer, fieldNames[i])\n\t\t\t\t}\n\t\t\t\ttimerKeys[timerFamilyID] = fieldNames[i]\n\t\t\t}\n\t\t}\n\t\tif err := validateOnTimerFn(fn); err != nil {\n\t\t\treturn err\n\t\t}\n\t} else {\n\t\tif len(pt) > 0 {\n\t\t\terr := errors.Errorf(\"ProcessElement doesn't use a TimerProvider, but Timer field is attached to the DoFn: %v\", pt)\n\t\t\treturn errors.SetTopLevelMsgf(err, \"ProcessElement doesn't use a TimerProvider, but Timer field is attached to the DoFn: %v\"+\n\t\t\t\t\", Ensure that you are using the TimerProvider to set and clear the timers.\", pt)\n\t\t}\n\t\tif err := validateOnTimerFn(fn); err == nil {\n\t\t\tactualErr := errors.New(\"OnTimer function is defined for the DoFn but no TimerProvider defined in ProcessElement\")\n\t\t\treturn errors.SetTopLevelMsgf(actualErr, \"OnTimer function is defined for the DoFn but no TimerProvider defined in ProcessElement.\"+\n\t\t\t\t\"Ensure that timers.Provider is defined in the ProcessElement and OnTimer methods of DoFn.\")\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// CombineFn represents a CombineFn.\ntype CombineFn Fn\n\n// SetupFn returns the \"Setup\" function, if present.\nfunc (f *CombineFn) SetupFn() *funcx.Fn {","sourceCodeStart":1430,"sourceCodeEnd":1466,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/go/pkg/beam/core/graph/fn.go#L1430-L1466","documentation":"A DoFn struct declares Timer fields, but its ProcessElement method does not accept a TimerProvider argument, so the SDK has no way to set or clear those timers. Beam requires that timers attached to a DoFn be driven through a TimerProvider in ProcessElement; fn.go raises this during graph validation.","triggerScenarios":"Declaring a `Timer` field on a DoFn whose ProcessElement signature is `ProcessElement(ctx, elem)` (no TimerProvider parameter), then constructing the pipeline.","commonSituations":"Adding a Timer field to an existing DoFn without updating ProcessElement; following older timer examples predating the TimerProvider API; stripping the TimerProvider parameter during refactoring while leaving the field.","solutions":["Add a TimerProvider parameter to ProcessElement, e.g. `func (d *MyDoFn) ProcessElement(ctx context.Context, tp timers.Provider, elem T) ...` and use it to set/clear the Timer fields.","Remove the Timer field (and any OnTimer method) if timers are no longer needed.","Verify the Timer field is registered with a valid spec and that OnTimer wiring matches the provider usage.","Check the Beam Go timer documentation for the current ProcessElement signature with TimerProvider."],"exampleFix":"// before\nfunc (d *MyDoFn) ProcessElement(ctx context.Context, elem string) { ... }\n// after\nfunc (d *MyDoFn) ProcessElement(ctx context.Context, tp timers.Provider, elem string) {\n    d.myTimer.Set(tp, deadline)\n}","handlingStrategy":"validation","validationCode":"// ensure any DoFn with Timer fields also takes a timers.Provider in ProcessElement\nfunc hasTimerProvider(fn interface{}) bool {\n    m := reflect.ValueOf(fn).MethodByName(\"ProcessElement\")\n    t := m.Type()\n    for i := 0; i < t.NumIn(); i++ {\n        if t.In(i).Implements(reflect.TypeOf((*timers.Provider)(nil)).Elem()) { return true }\n    }\n    return false\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["When adding a Timer field, update ProcessElement and OnTimer together.","Follow current Beam Go timer examples; older APIs differ."],"tags":["beam","go","dofn","timer","signature-validation"],"backgroundTag":"missing-required-argument","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"}