apache/beam · error

CreateInitialRestriction has unexpected number of return val

Error message

CreateInitialRestriction has unexpected number of return values: %v

What it means

Beam's SDF invoker (sdf_invokers_arity.tmpl) validates that a user's CreateInitialRestriction method returns 1 value (the restriction) or 2 values (restriction + error). Any other return arity cannot be dispatched and panics at runtime. This guards user DoFn signatures for splittable DoFns.

Source

Thrown at sdks/go/pkg/beam/core/runtime/exec/sdf_invokers_arity.tmpl:65

	{{end}}
{{end}}
{{end}}
	default:
		if len(n.fn.Param) < 1 || len(n.fn.Param) > 3 {
			return errors.Errorf("CreateInitialRestriction has unexpected number of parameters: %v", len(n.fn.Param))
		}

		n.call = func() (rest any, err error) {
			ret := n.fn.Fn.Call(n.args)

			switch len(ret) {
			case 1:
				return ret[0], nil
			case 2:
				return ret[0], asError(ret[1])
			}

			panic(fmt.Sprintf("CreateInitialRestriction has unexpected number of return values: %v", len(ret)))
		}
	}

	return nil
}

func (n *srInvoker) initCallFn() error {
	// Expects a signature of the form:
	// (context.Context?, key?, value, restriction) ([]restriction, error?)
	// TODO(BEAM-9643): Link to full documentation.
	switch fnT := n.fn.Fn.(type) {
{{range $out := upto 3}}
{{range $in := upto 5}}
    {{if gt $out 0}}
    {{if gt $in 1}}
	case reflectx.Func{{$in}}x{{$out}}:
		n.call = func() (splits any, err error) {
			{{mktuplef $out "r%v"}} := fnT.Call{{$in}}x{{$out}}({{mktuplef $in "n.args[%v]"}})

View on GitHub (pinned to 12126d8942)

Solutions

  1. Change CreateInitialRestriction to return exactly (Restriction) or (Restriction, error)
  2. Check the Beam Go SDF docs for the required method signatures
  3. If the signature looks correct, ensure you are on a Beam version matching your DoFn's registration code

Example fix

// before
func (fn *sdfFn) CreateInitialRestriction(r Range) (Rest, Extra, error) { ... }

// after
func (fn *sdfFn) CreateInitialRestriction(r Range) (Rest, error) { ... }
Defensive patterns

Strategy: validation

Validate before calling

t := reflect.TypeOf(fn).Method(0) // or MethodByName("CreateInitialRestriction")
if t.Type.NumOut() != 1 && t.Type.NumOut() != 2 {
    return fmt.Errorf("CreateInitialRestriction must return 1 or 2 values")
}

Type guard

func validCreateInitialRestriction(fn interface{}) bool {
    m := reflect.ValueOf(fn).MethodByName("CreateInitialRestriction")
    if !m.IsValid() { return false }
    n := m.Type().NumOut()
    return n == 1 || n == 2
}

Try / catch

defer func() {
    if r := recover(); strings.Contains(fmt.Sprint(r), "CreateInitialRestriction has unexpected number of return values") {
        log.Fatalf("SDF signature error: %v", r)
    }
}()

Prevention

When it happens

Trigger: Defining a splittable DoFn whose CreateInitialRestriction returns 0 or 3+ values, then executing a pipeline with that SDF.

Common situations: Misremembering the SDF method contract; copy-paste refactor leaving extra return values; mixing up CreateInitialRestriction with other method signatures.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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