apache/beam · error

batch.groupIntoBatchesBufferedFn: unexpected timer family

Error message

batch.groupIntoBatchesBufferedFn: unexpected timer family %q

What it means

This panic fires in OnTimer when the delivered timer's Family matches neither fn.Buffering.Family nor fn.WindowEnd.Family. The DoFn only knows how to handle its own two timer families; an unknown family means a misconfigured or foreign timer is firing for this step, and the library treats it as an unrecoverable internal bug.

Solutions

  1. Check whether the pipeline was updated between versions with changed timer family names; do a clean restart (drain, cancel all state, fresh job) instead of in-place update.
  2. Verify no other DoFn/transform shares the same step and timer namespace.
  3. Report to the runner if stale timers from a cancelled job are still firing.
  4. Upgrade Beam to get family-name stability fixes for job updates.
  5. As a diagnostic, log timer.Family before the switch to identify its origin.

Example fix

// before: family names changed across a job update
fn.Buffering = tm.ProcessTime("buf_v2")
// after: keep family names stable across deployments, or fully restart the job
fn.Buffering = tm.ProcessTime("buffering") // same family name as previous version
Defensive patterns

Strategy: validation

Validate before calling

// Before switching job code in-place, diff timer family names between old and
// new versions; if changed, plan a full drain + fresh job restart instead.

Prevention

When it happens

Trigger: A timer callback delivers a family string that does not equal the Buffering or WindowEnd family — e.g. the pipeline was updated and an old version of the same step left timers with changed family names firing against new code, or a runner reuses/delivers timer IDs incorrectly.

Common situations: Job update (drain + restart with modified code) where the timer family string changed between versions; state/timer resurrection after job migration; runner bugs delivering stale timers from a previous job to a recycled worker.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


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

Appendix: source

Thrown at sdks/go/pkg/beam/transforms/batch/batch.go:427

		fn.flush(sp, tp, key, emit)
		return
	}
	if fn.BatchSizeBytes > 0 && newBytes >= fn.BatchSizeBytes {
		fn.flush(sp, tp, key, emit)
		return
	}
}

func (fn *groupIntoBatchesBufferedFn) OnTimer(
	ctx context.Context, ts beam.EventTime, sp state.Provider, tp timers.Provider,
	key typex.T, timer timers.Context, emit func(typex.T, []typex.V),
) {
	fn.codec.init(fn.ValueType.T)
	switch timer.Family {
	case fn.Buffering.Family, fn.WindowEnd.Family:
		fn.flush(sp, tp, key, emit)
	default:
		panic(fmt.Sprintf(
			"batch.groupIntoBatchesBufferedFn: unexpected timer family %q", timer.Family))
	}
}

func (fn *groupIntoBatchesBufferedFn) flush(
	sp state.Provider, tp timers.Provider, key typex.T, emit func(typex.T, []typex.V),
) {
	buf, ok, err := fn.Buffer.Read(sp)
	if err != nil {
		panic(err)
	}
	if !ok || len(buf) == 0 {
		return
	}

	out := make([]typex.V, len(buf))
	for i, b := range buf {
		out[i] = fn.codec.decode(b)

View on GitHub (pinned to 12126d8942)