apache/beam · error

WatermarkEstimatorState fn %v has unexpected number of param

Error message

WatermarkEstimatorState fn %v has unexpected number of parameters: %v

What it means

The WatermarkEstimatorState accessor function on an SDF must take exactly zero or one parameter (the watermark estimator). initCallFn raises this error when the registered function's parameter count falls outside the supported forms, during invoker initialization.

Source

Thrown at sdks/go/pkg/beam/core/runtime/exec/sdf_invokers.go:520

		}
		return nil
	}
	// Expects a signature of the form:
	// (state) sdf.WatermarkEstimator
	switch fnT := n.fn.Fn.(type) {
	case reflectx.Func1x1:
		n.call = func(we sdf.WatermarkEstimator) any {
			return fnT.Call1x1(we)
		}
	default:
		switch len(n.fn.Param) {
		case 1:
			n.call = func(we sdf.WatermarkEstimator) any {
				n.args[0] = we
				return n.fn.Fn.Call(n.args)[0]
			}
		default:
			return errors.Errorf("WatermarkEstimatorState fn %v has unexpected number of parameters: %v",
				n.fn.Fn.Name(), len(n.fn.Param))
		}
	}
	return nil
}

// Invoke calls WatermarkEstimatorState given a restriction and returns an sdf.RTracker.
func (n *wesInvoker) Invoke(we sdf.WatermarkEstimator) any {
	return n.call(we)
}

// Reset zeroes argument entries in the cached slice to allow values to be
// garbage collected after the bundle ends.
func (n *wesInvoker) Reset() {
	for i := range n.args {
		n.args[i] = nil
	}
}

View on GitHub (pinned to 12126d8942)

Solutions

  1. Change WatermarkEstimatorState to take exactly one sdf.WatermarkEstimator parameter.
  2. Use the zero-parameter form if the estimator itself is unnecessary to extract state.
  3. Remove any additional element/restriction parameters from the signature.
  4. Validate the DoFn signature with a unit test that constructs the pipeline before deployment.

Example fix

// before
func (fn *mySdf) WatermarkEstimatorState(we sdf.WatermarkEstimator, ts typex.EventTime) W { ... }
// after
func (fn *mySdf) WatermarkEstimatorState(we sdf.WatermarkEstimator) W { ... }
Defensive patterns

Strategy: validation

Validate before calling

t := reflect.TypeOf(fn.WatermarkEstimatorState)
if t.NumIn() > 1 {
    return fmt.Errorf("WatermarkEstimatorState must take at most 1 parameter, has %d", t.NumIn())
}

Try / catch

if err != nil {
    if strings.Contains(err.Error(), "WatermarkEstimatorState fn") {
        // reduce to func(we sdf.WatermarkEstimator) W
    }
    return err
}

Prevention

When it happens

Trigger: Registering a WatermarkEstimatorState fn like func(we sdf.WatermarkEstimator, el T) W (2 params) or any other unsupported arity; the invoker builds a call path only for 0 or 1 params and otherwise errors at sdf_invokers.go:520.

Common situations: Copy-pasting the estimator method shape from another hook with more parameters, or accidentally adding a second argument when adapting a watermark estimator to a new DoFn.

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/43fcdc13abf3f03a. Report an issue: GitHub.