{"record":{"id":"794e0d46558a0ac0","repo":"apache/beam","slug":"no-root-units","errorCode":null,"errorMessage":"no root units","messagePattern":"no root units","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"sdks/go/pkg/beam/core/runtime/exec/plan.go","lineNumber":83,"sourceCode":"\t\t}\n\t\tif s, ok := u.(*DataSource); ok {\n\t\t\tsource = s\n\t\t}\n\t\tif p, ok := u.(*PCollection); ok {\n\t\t\tpcols = append(pcols, p)\n\t\t}\n\t\tif pd, ok := u.(*ParDo); ok && pd.HasOnTimer() {\n\t\t\tif onTimers == nil {\n\t\t\t\tonTimers = map[string]*ParDo{}\n\t\t\t}\n\t\t\tonTimers[pd.PID] = pd\n\t\t}\n\t\tif p, ok := u.(needsBundleFinalization); ok {\n\t\t\tp.AttachFinalizer(&bf)\n\t\t}\n\t}\n\tif len(roots) == 0 {\n\t\treturn nil, errors.Errorf(\"no root units\")\n\t}\n\n\tif len(onTimers) > 0 {\n\t\tsource.OnTimerTransforms = onTimers\n\t}\n\n\treturn &Plan{\n\t\tid:     id,\n\t\tstatus: Initializing,\n\t\troots:  roots,\n\t\tunits:  units,\n\t\tpcols:  pcols,\n\t\tbf:     &bf,\n\t\tsource: source,\n\t}, nil\n}\n\nfunc (p *Plan) getStatus() Status {","sourceCodeStart":65,"sourceCodeEnd":101,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/go/pkg/beam/core/runtime/exec/plan.go#L65-L101","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Ensure a *DataSource unit is included in the units passed to NewPlan.","Check that the root unit's type assertion (u.(Root)) can succeed - the unit must implement the Root interface.","Review pipeline translation code to confirm the source transform maps to a DataSource unit."],"exampleFix":"// before\nunits := []exec.Unit{pardo1, pardo2}\nplan, err := exec.NewPlan(id, units) // no root\n// after\nunits := []exec.Unit{dataSource, pardo1, pardo2}\nplan, err := exec.NewPlan(id, units)","handlingStrategy":"validation","validationCode":"hasRoot := false\nfor _, u := range units {\n    if _, ok := u.(exec.Root); ok {\n        hasRoot = true\n        break\n    }\n}\nif !hasRoot {\n    return fmt.Errorf(\"units must include a Root (DataSource)\")\n}\nplan, err := exec.NewPlan(id, units)","typeGuard":"func hasRootUnit(units []exec.Unit) bool {\n    for _, u := range units {\n        if _, ok := u.(exec.Root); ok {\n            return true\n        }\n    }\n    return false\n}","tryCatchPattern":"plan, err := exec.NewPlan(id, units)\nif err != nil {\n    if strings.Contains(err.Error(), \"no root units\") {\n        return fmt.Errorf(\"pipeline translation produced no DataSource: %w\", err)\n    }\n    return err\n}","preventionTips":["Always include a *DataSource in the units passed to NewPlan.","Verify transform translation maps source transforms to DataSource units.","Write a test asserting every constructed plan contains exactly one root."],"tags":["go","apache-beam","validation","plan"],"backgroundTag":"missing-required-argument","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-20T03:17:13.778Z"}