apache/beam · error

RestrictionSize has unexpected number of return values: %v

Error message

RestrictionSize has unexpected number of return values: %v

What it means

The SDF invoker requires RestrictionSize to return either 1 value (float64 size) or 2 values (size + error). Any other return count panics, since the generated dispatcher cannot map it. The size is cast to float64, so the first return must also be float64-compatible.

Source

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

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

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

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

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

	return nil
}

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

View on GitHub (pinned to 12126d8942)

Solutions

  1. Make RestrictionSize return exactly (float64) or (float64, error)
  2. Ensure the restriction type passed in matches the one produced by CreateInitialRestriction
  3. Cross-check with Beam Go SDF examples in the docs

Example fix

// before
func (fn *sdfFn) RestrictionSize(r Rest) (int, string, error) { ... }

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

Strategy: validation

Validate before calling

m := reflect.ValueOf(fn).MethodByName("RestrictionSize")
if m.IsValid() {
    t := m.Type()
    if (t.NumOut() != 1 && t.NumOut() != 2) || t.Out(0).Kind() != reflect.Float64 {
        return fmt.Errorf("RestrictionSize must return float64 (plus optional error)")
    }
}

Type guard

func validRestrictionSize(fn interface{}) bool {
    m := reflect.ValueOf(fn).MethodByName("RestrictionSize")
    if !m.IsValid() { return false }
    t := m.Type()
    return (t.NumOut() == 1 || t.NumOut() == 2) && t.Out(0).Kind() == reflect.Float64
}

Try / catch

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

Prevention

When it happens

Trigger: A splittable DoFn whose RestrictionSize returns 0 or 3+ values (or whose first return is not a numeric float64), executed in a pipeline.

Common situations: Returning int size without float64; adding extra return values during refactoring; misunderstanding the SDF size-estimation contract.

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/08a9dae470ee4f10. Report an issue: GitHub.