apache/beam · error

found %v inbound, want %v

Error message

found %v inbound, want %v

What it means

makeSideInputs validates that a DoFn's inbound edges match its side inputs: there must be exactly len(side)+1 inbound edges (the main input plus each side input). If the counts disagree, the pipeline graph does not match the function signature, so the library refuses to build the side inputs and fails the stage at construction time.

Source

Thrown at sdks/go/pkg/beam/core/runtime/exec/fn.go:451

// ret5 handles processing five return values.
func (n *invoker) ret5(pn typex.PaneInfo, ws []typex.Window, ts typex.EventTime, r0, r1, r2, r3, r4 any) (*FullValue, error) {
	if r4 != nil {
		return nil, r4.(error)
	}
	if r3 == nil {
		panic(fmt.Sprintf("invoker.ret5: cannot return a nil process continuation from function %v", n.fn))
	}
	n.ret = FullValue{Windows: ws, Timestamp: r0.(typex.EventTime), Elm: r1, Elm2: r2, Continuation: r3.(sdf.ProcessContinuation)}
	return &n.ret, nil
}

func makeSideInputs(ctx context.Context, w typex.Window, side []SideInputAdapter, reader StateReader, fn *funcx.Fn, in []*graph.Inbound) ([]ReusableInput, error) {
	if len(side) == 0 {
		return nil, nil // ok: no side input
	}

	if len(in) != len(side)+1 {
		return nil, errors.Errorf("found %v inbound, want %v", len(in), len(side)+1)
	}
	param := fn.Params(funcx.FnValue | funcx.FnIter | funcx.FnReIter | funcx.FnMultiMap)
	if len(param) <= len(side) {
		return nil, errors.Errorf("found %v params, want >%v", len(param), len(side))
	}

	// The side input are last of the above params, so we can compute the offset easily.
	offset := len(param) - len(side)

	var ret []ReusableInput
	for i, adapter := range side {
		inKind := in[i+1].Kind
		params := fn.Param[param[i+offset]].T
		// Handle MultiMaps separately since they require more/different information
		// than the other side inputs
		if inKind == graph.MultiMap {
			s := makeMultiMap(ctx, params, side[i], reader, w)
			ret = append(ret, s)

View on GitHub (pinned to 12126d8942)

Solutions

  1. Count the side inputs declared in the DoFn signature and ensure exactly one beam.SideInput is passed per side-input parameter to beam.ParDo, with exactly one main input.
  2. Re-run the pipeline so expansion and execution use the same SDK version; stale expansion artifacts can produce mismatched inbound counts.
  3. Inspect the DoFn signature for extra/missing parameters (context, emit functions) that shift the main vs side input split.

Example fix

// before
beam.ParDo(s, &myFn{ /* declares 1 side input */ }, col, beam.SideInput{Input: other1}, beam.SideInput{Input: other2})

// after (fn has only 1 side input param)
beam.ParDo(s, &myFn{}, col, beam.SideInput{Input: other1})
Defensive patterns

Strategy: validation

Validate before calling

sideInputs := /* count beam.SideInput args passed to beam.ParDo */
inbounds := /* inbound edges of the node, from pipeline graph or expansion output */
if inboundCount != sideInputs+1 {
    return fmt.Errorf("ParDo %T: %d side inputs require %d inbound edges, got %d", fn, sideInputs, sideInputs+1, inboundCount)
}

Prevention

When it happens

Trigger: Calling initSideInput (during exec.Plan Up/processing-time setup) for a DoFn whose graph.Inbound list does not equal len(side)+1, e.g. a DoFn declares 2 side inputs but the node has 2 or 4 inbound edges.

Common situations: A DoFn was changed to accept an extra side input (or an extra main-input param) but the pipeline wiring in beam.ParDo/beam.TryParDo was not updated; a miscount when passing side inputs to beam.ParDo; pipeline graph produced by an older SDK version being re-expanded by a newer runner.

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/1ecb3a183ded8b92. Report an issue: GitHub.