{"record":{"id":"e3a3cca1a9afebf3","repo":"apache/beam","slug":"node-type-not-bound-v","errorCode":null,"errorMessage":"Node type not bound: %v","messagePattern":"Node type not bound: (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"sdks/go/pkg/beam/core/graph/graph.go","lineNumber":74,"sourceCode":"\tg.scopes = append(g.scopes, s)\n\treturn s\n}\n\n// NewEdge creates a new edge of the graph in the supplied scope.\nfunc (g *Graph) NewEdge(parent *Scope) *MultiEdge {\n\tif parent == nil {\n\t\tpanic(\"Scope is nil\")\n\t}\n\tid := len(g.edges) + 1\n\te := &MultiEdge{id: id, parent: parent}\n\tg.edges = append(g.edges, e)\n\treturn e\n}\n\n// NewNode creates a new node in the graph of the supplied fulltype.\nfunc (g *Graph) NewNode(t typex.FullType, w *window.WindowingStrategy, bounded bool) *Node {\n\tif !typex.IsBound(t) {\n\t\tpanic(fmt.Sprintf(\"Node type not bound: %v\", t))\n\t}\n\tid := len(g.nodes) + 1\n\tn := &Node{id: id, t: t, w: w, bounded: bounded}\n\tg.nodes = append(g.nodes, n)\n\treturn n\n}\n\n// Build performs finalization on the graph. It verifies the correctness of the\n// graph structure, typechecks the plan and returns a slice of the edges in\n// the graph.\nfunc (g *Graph) Build() ([]*MultiEdge, []*Node, error) {\n\t// Build a map of all nodes listed in g.nodes.\n\tnodes := make(map[*Node]bool)\n\tfor _, n := range g.nodes {\n\t\tnodes[n] = true\n\t\tif n.Coder == nil {\n\t\t\treturn nil, nil, errors.Errorf(\"node %v in graph has undefined coder\", n.id)\n\t\t}","sourceCodeStart":56,"sourceCodeEnd":92,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/go/pkg/beam/core/graph/graph.go#L56-L92","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nt := typex.NewVariable(\"T\")\nn := g.NewNode(t, w, true) // unbound\n// after\nt := typex.New(reflect.TypeOf(Foo{}))\nn := g.NewNode(t, w, true)","handlingStrategy":"validation","validationCode":"if !typex.IsBound(t) {\n\treturn fmt.Errorf(\"type %v is not bound; resolve to a concrete type before NewNode\", t)\n}","typeGuard":"func isConcreteFullType(t typex.FullType) bool { return typex.IsBound(t) }","tryCatchPattern":"func safeNewNode(g *graph.Graph, t typex.FullType, w *window.WindowingStrategy, bounded bool) (n *graph.Node, err error) {\n\tdefer func() { if r := recover(); r != nil { err = fmt.Errorf(\"newNode: %v\", r) } }()\n\treturn g.NewNode(t, w, bounded), nil\n}","preventionTips":["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"],"tags":["go","beam","graph","types"],"backgroundTag":"invalid-argument-value","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"}