apache/beam · error
Node type not bound
Error message
Node type not bound: %v
What it means
Graph.NewNode panics when the supplied typex.FullType is not bound, i.e. its type has unresolved or missing type information (typex.IsBound fails). Beam graph nodes require fully resolved concrete types to plan encoding and windowing.
Solutions
- Pass a concrete typex.FullType, e.g. typex.New(reflect.TypeOf(Foo{})), not a variable type
- Resolve any typex.T variables via substitution before node creation
- Log/print the type before NewNode to identify the unbound component
Example fix
// before
t := typex.NewVariable("T")
n := g.NewNode(t, w, true) // unbound
// after
t := typex.New(reflect.TypeOf(Foo{}))
n := g.NewNode(t, w, true) Defensive patterns
Strategy: validation
Validate before calling
if !typex.IsBound(t) {
return fmt.Errorf("type %v is not bound; resolve to a concrete type before NewNode", t)
} Type guard
func isConcreteFullType(t typex.FullType) bool { return typex.IsBound(t) } Try / catch
func safeNewNode(g *graph.Graph, t typex.FullType, w *window.WindowingStrategy, bounded bool) (n *graph.Node, err error) {
defer func() { if r := recover(); r != nil { err = fmt.Errorf("newNode: %v", r) } }()
return g.NewNode(t, w, bounded), nil
} Prevention
- Build FullTypes from concrete reflect.Types (typex.New(reflect.TypeOf(T{})))
- Avoid typex.NewVariable in production graph construction
- Resolve type variables via substitution before creating nodes
When it happens
Trigger: Calling graph.NewNode(t, w, bounded) with an unbound type such as a type with typex.NewVariable type variables, an unresolved generic, or a zero-value FullType built from an invalid reflect.Type.
Common situations: Constructing graph nodes in custom transforms or tests using typex.New/Variable incorrectly; reflection-based code that failed to resolve a concrete type; misuse of typex APIs introduced while hand-building pipeline graphs.
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
- bad output type
- failed to add scope tree
- invalid pipeline
- needs at least 1 input
- node in graph has undefined coder
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/e3a3cca1a9afebf3.
Report an issue: GitHub.
Appendix: source
Thrown at sdks/go/pkg/beam/core/graph/graph.go:74
g.scopes = append(g.scopes, s)
return s
}
// NewEdge creates a new edge of the graph in the supplied scope.
func (g *Graph) NewEdge(parent *Scope) *MultiEdge {
if parent == nil {
panic("Scope is nil")
}
id := len(g.edges) + 1
e := &MultiEdge{id: id, parent: parent}
g.edges = append(g.edges, e)
return e
}
// NewNode creates a new node in the graph of the supplied fulltype.
func (g *Graph) NewNode(t typex.FullType, w *window.WindowingStrategy, bounded bool) *Node {
if !typex.IsBound(t) {
panic(fmt.Sprintf("Node type not bound: %v", t))
}
id := len(g.nodes) + 1
n := &Node{id: id, t: t, w: w, bounded: bounded}
g.nodes = append(g.nodes, n)
return n
}
// Build performs finalization on the graph. It verifies the correctness of the
// graph structure, typechecks the plan and returns a slice of the edges in
// the graph.
func (g *Graph) Build() ([]*MultiEdge, []*Node, error) {
// Build a map of all nodes listed in g.nodes.
nodes := make(map[*Node]bool)
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)
}View on GitHub (pinned to 12126d8942)