apache/beam · error

trigger argument to trigger.Repeat() cannot be nil

Error message

trigger argument to trigger.Repeat() cannot be nil

What it means

trigger.Repeat panics when its Trigger argument is nil. Repeat wraps a sub-trigger that fires repeatedly; a nil sub-trigger is meaningless and would fail later during trigger evaluation, so the SDK fails fast at construction.

Solutions

  1. Pass a concrete trigger such as trigger.AfterCount(1) or trigger.AfterFirst() to Repeat
  2. Fix the construction path that returned nil (unmatched config value, unhandled trigger kind)
  3. Note trigger.Repeat(trigger.AfterCount(1)) is equivalent to trigger.Always() — use that directly if applicable

Example fix

// before
var t trigger.Trigger // nil
tw := trigger.Repeat(t)
// after
tw := trigger.Repeat(trigger.AfterCount(1))
Defensive patterns

Strategy: validation

Validate before calling

if t == nil {
	return errors.New("sub-trigger is nil; supply e.g. trigger.AfterCount(1)")
}

Type guard

func validTrigger(t trigger.Trigger) bool { return t != nil }

Try / catch

func safeRepeat(t trigger.Trigger) (tr *trigger.RepeatTrigger, err error) {
	defer func() { if r := recover(); r != nil { err = fmt.Errorf("trigger.Repeat: %v", r) } }()
	return trigger.Repeat(t), nil
}

Prevention

When it happens

Trigger: Calling trigger.Repeat(nil) directly, or passing a trigger variable that was never initialized (e.g. a lookup that missed, or a conditional that skipped assignment).

Common situations: Building triggers from configuration where the configured sub-trigger name didn't resolve; helper functions returning nil Trigger on unknown kinds that is then wrapped in Repeat.

Related errors


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

Appendix: source

Thrown at sdks/go/pkg/beam/core/graph/window/trigger/trigger.go:208

// String implements the Stringer interface and returns trigger details as a string.
func (t *RepeatTrigger) String() string {
	return fmt.Sprintf("%#v", t)
}

func (t RepeatTrigger) trigger() {}

// SubTrigger returns the trigger to be repeated.
func (t *RepeatTrigger) SubTrigger() Trigger {
	return t.subtrigger
}

// Repeat constructs a trigger that fires a trigger repeatedly
// once the condition has been met.
//
// Ex: trigger.Repeat(trigger.AfterCount(1)) is same as trigger.Always().
func Repeat(t Trigger) *RepeatTrigger {
	if t == nil {
		panic("trigger argument to trigger.Repeat() cannot be nil")
	}
	return &RepeatTrigger{subtrigger: t}
}

// AfterEndOfWindowTrigger provides option to set triggers for early and late firing.
type AfterEndOfWindowTrigger struct {
	earlyFiring Trigger
	lateFiring  Trigger
}

// String implements the Stringer interface and returns trigger details as a string.
func (t *AfterEndOfWindowTrigger) String() string {
	return fmt.Sprintf("%#v", t)
}

func (t AfterEndOfWindowTrigger) trigger() {}

// Early returns the Early Firing trigger for AfterEndOfWindowTrigger.

View on GitHub (pinned to 12126d8942)