apache/beam · error

no root units

Error message

no root units

What it means

A valid plan must contain at least one Root unit (e.g. DataSource). exec.NewPlan throws this error when the supplied units slice contains no unit implementing the Root interface, since a plan without a source of data cannot execute.

Solutions

  1. Ensure a *DataSource unit is included in the units passed to NewPlan.
  2. Check that the root unit's type assertion (u.(Root)) can succeed - the unit must implement the Root interface.
  3. Review pipeline translation code to confirm the source transform maps to a DataSource unit.

Example fix

// before
units := []exec.Unit{pardo1, pardo2}
plan, err := exec.NewPlan(id, units) // no root
// after
units := []exec.Unit{dataSource, pardo1, pardo2}
plan, err := exec.NewPlan(id, units)
Defensive patterns

Strategy: validation

Validate before calling

hasRoot := false
for _, u := range units {
    if _, ok := u.(exec.Root); ok {
        hasRoot = true
        break
    }
}
if !hasRoot {
    return fmt.Errorf("units must include a Root (DataSource)")
}
plan, err := exec.NewPlan(id, units)

Type guard

func hasRootUnit(units []exec.Unit) bool {
    for _, u := range units {
        if _, ok := u.(exec.Root); ok {
            return true
        }
    }
    return false
}

Try / catch

plan, err := exec.NewPlan(id, units)
if err != nil {
    if strings.Contains(err.Error(), "no root units") {
        return fmt.Errorf("pipeline translation produced no DataSource: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: Calling NewPlan with only non-root units (e.g. only ParDos/Flatten without a DataSource), or a translation bug where the DataSource unit failed a type assertion (it must be a concrete *DataSource).

Common situations: Custom runners or tests constructing plans from transform lists without including the DataSource; refactors changing unit types so the root type no longer implements Root.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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

Appendix: source

Thrown at sdks/go/pkg/beam/core/runtime/exec/plan.go:83

		}
		if s, ok := u.(*DataSource); ok {
			source = s
		}
		if p, ok := u.(*PCollection); ok {
			pcols = append(pcols, p)
		}
		if pd, ok := u.(*ParDo); ok && pd.HasOnTimer() {
			if onTimers == nil {
				onTimers = map[string]*ParDo{}
			}
			onTimers[pd.PID] = pd
		}
		if p, ok := u.(needsBundleFinalization); ok {
			p.AttachFinalizer(&bf)
		}
	}
	if len(roots) == 0 {
		return nil, errors.Errorf("no root units")
	}

	if len(onTimers) > 0 {
		source.OnTimerTransforms = onTimers
	}

	return &Plan{
		id:     id,
		status: Initializing,
		roots:  roots,
		units:  units,
		pcols:  pcols,
		bf:     &bf,
		source: source,
	}, nil
}

func (p *Plan) getStatus() Status {

View on GitHub (pinned to 12126d8942)