apache/beam · error
node %v in graph is unconnected
Error message
node %v in graph is unconnected
What it means
Graph.Build() checks that every node in g.nodes is reachable via at least one MultiEdge output. A node with no incoming edge means it's disconnected from the pipeline (nothing consumes it), so Build returns 'node %v in graph is unconnected'.
Source
Thrown at sdks/go/pkg/beam/core/graph/graph.go:106
for _, n := range g.nodes {
nodes[n] = true
if n.Coder == nil {
return nil, nil, errors.Errorf("node %v in graph has undefined coder", n.id)
}
}
// Build a map of all nodes that are reachable by g.edges.
reachable := make(map[*Node]*MultiEdge)
for _, e := range g.edges {
for _, i := range e.Input {
reachable[i.From] = e
}
for _, o := range e.Output {
reachable[o.To] = e
}
}
for n := range nodes {
if _, ok := reachable[n]; !ok {
return nil, nil, errors.Errorf("node %v in graph is unconnected", n.id)
}
}
for n, e := range reachable {
if _, ok := nodes[n]; !ok {
return nil, nil, errors.Errorf("node %v is reachable by edge %v, but it's not in same graph", n.id, e.id)
}
}
return g.edges, g.nodes, nil
}
func (g *Graph) String() string {
var nodes []string
for _, node := range g.nodes {
nodes = append(nodes, node.String())
}
var edges []string
for _, edge := range g.edges {
edges = append(edges, edge.String())View on GitHub (pinned to 12126d8942)
Solutions
- Connect the orphan node to a downstream transform (e.g. pass it as an input to beam.ParDo or a sink like beam.io.Write).
- If the PCollection is intentionally unused, remove the transform producing it.
- When hand-building graphs, register the node via an edge (g.NewEdge and set Input/Output) before Build().
- Review custom composite transform expansion so all outputs are either consumed or deliberately rooted.
Defensive patterns
Strategy: validation
Prevention
- Consume every PCollection produced by a transform, or don't produce it.
- When using the low-level graph API, wire each node into an edge before Build().
When it happens
Trigger: Creating a node (e.g. via beam.Impulse/beam.Create output or manual g.NewNode) without wiring it as input to any transform before calling Build().
Common situations: Manually constructing graphs with the low-level API and forgetting to connect an output; a transform whose output PCollection is dropped silently in custom code; SDK bugs when composing custom composite transforms.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- node %v is reachable by edge %v, but it's not in same graph
- too few params
- too few inputs: forgot an input or to annotate options?
- too many inputs
- needs at least 1 input
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/fb4713db77f83199.
Report an issue: GitHub.