apache/beam · error
node %v in graph has undefined coder
Error message
node %v in graph has undefined coder
What it means
Graph.Build() finalizes the Beam DAG and verifies every node has a coder (the serialization spec for its element type). During expansion/translation Beam normally assigns coders automatically; a nil coder means graph construction left a node untyped, so Build refuses to proceed with 'node %v in graph has undefined coder'.
Source
Thrown at sdks/go/pkg/beam/core/graph/graph.go:91
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)
}
}
// 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 {View on GitHub (pinned to 12126d8942)
Solutions
- Find the DoFn/transform producing that node and give ProcessElement concrete encodable types (no interface{}, func, or chan).
- If using the low-level graph API, set n.Coder explicitly before Build().
- Check for a Beam SDK bug — search the error's node id against your pipeline; upgrade to the latest Beam release.
- Register custom types with beam.Encoder/coder registration so inference succeeds.
Defensive patterns
Strategy: try-catch
Try / catch
if _, _, err := g.Build(); err != nil {
if strings.Contains(err.Error(), "undefined coder") {
// inspect node id, fix producing DoFn types or set Coder explicitly
log.Fatalf("coder inference failed: %v", err)
}
return err
} Prevention
- Avoid interface{}, func, or chan types in DoFn ProcessElement parameters.
- Register custom types for coder inference before building pipelines.
When it happens
Trigger: Calling g.Build() after adding edges whose input/output nodes were never given a coder, typically from custom transform construction (beam.Create with unsupported types, custom DoFn signatures Beam can't infer, or manually assembled Graphs).
Common situations: Using a custom DoFn whose ProcessElement parameter type can't be encoded (e.g. interface{}, chan, func types); building nodes directly via the low-level graph API without setting Coder; SDK/runner bugs when inserting cross-language transforms.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- too few params
- too few inputs: forgot an input or to annotate options?
- too many inputs
- varint too long
- needs at least 1 input
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/23c61ef447e4c4ab.
Report an issue: GitHub.