apache/beam · error

Init() not called

Error message

Init() not called

What it means

This panic is thrown by iterValue.Reset in the Beam Go SDK execution engine when an iterator-typed side input value is Reset or used before Init() has initialized its underlying element stream (v.cur). The library requires the Init lifecycle step to attach a ReStream before iteration or teardown. Resetting an uninitialized value means the plan is being driven out of order.

Solutions

  1. Ensure Init() is called on every ReusableInput before Reset() or iteration (the normal plan lifecycle does this in unit initialization).
  2. Check that the upstream node that provides the ReStream actually executed and did not fail/skip initialization.
  3. If you manage exec plans yourself, guard Reset with a nil check on the underlying stream.
  4. Upgrade the SDK — if this occurs during normal pipeline runs it is an engine lifecycle bug worth reporting.

Example fix

// before
v := exec.MakeIterValue(...) // direct construction
v.Reset()
// after
v := exec.MakeIterValue(...)
v.Init(ctx, stream) // initialize before use
err := v.Reset()
Defensive patterns

Strategy: try-catch

Validate before calling

// Go has no pre-call check on unexported state; validate your plan construction instead:
// ensure every ReusableInput in the plan has Init() called before Reset()/use.

Try / catch

func safeReset(v interface{ Reset() error }) (err error) {
	defer func() {
		if r := recover(); r != nil {
			if s, ok := r.(string); ok && s == "Init() not called" {
				err = fmt.Errorf("input used before Init: %v", r)
				return
			}
			panic(r)
		}
	}()
	return v.Reset()
}

Prevention

When it happens

Trigger: Calling Reset() on an iterValue whose Init() was never called — typically when the exec plan is invoked without a prior initialization pass, or a custom/modified plan node skips Init on its inputs before cleanup or re-use.

Common situations: Hand-constructed or cached execution plans reused across bundles; unit tests that build an iterValue directly and call Reset without Init; engine bugs where a bundle is torn down before inputs were initialized (e.g. after upstream failure).

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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

Appendix: source

Thrown at sdks/go/pkg/beam/core/runtime/exec/input.go:145

	return ret
}

func (v *iterValue) Init() error {
	cur, err := v.s.Open()
	if err != nil {
		return err
	}
	v.cur = cur
	return nil
}

func (v *iterValue) Value() any {
	return v.fn
}

func (v *iterValue) Reset() error {
	if v.cur == nil {
		panic("Init() not called")
	}
	if err := v.cur.Close(); err != nil {
		return err
	}
	v.cur = nil
	return nil
}

func (v *iterValue) invoke(args []reflect.Value) []reflect.Value {
	if v.cur == nil {
		panic("Init() not called")
	}
	elm, err := v.cur.Read()
	if err != nil {
		if err == io.EOF {
			return []reflect.Value{reflect.ValueOf(false)}
		}
		panic(errors.Wrap(err, "broken stream"))

View on GitHub (pinned to 12126d8942)