{"record":{"id":"2a2953b08853a11a","repo":"apache/beam","slug":"node-v-is-reachable-by-edge-v-but-it-s-not-in-same-graph","errorCode":null,"errorMessage":"node %v is reachable by edge %v, but it's not in same graph","messagePattern":"node (.+?) is reachable by edge (.+?), but it's not in same graph","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"sdks/go/pkg/beam/core/graph/graph.go","lineNumber":111,"sourceCode":"\t}\n\t// Build a map of all nodes that are reachable by g.edges.\n\treachable := make(map[*Node]*MultiEdge)\n\tfor _, e := range g.edges {\n\t\tfor _, i := range e.Input {\n\t\t\treachable[i.From] = e\n\t\t}\n\t\tfor _, o := range e.Output {\n\t\t\treachable[o.To] = e\n\t\t}\n\t}\n\tfor n := range nodes {\n\t\tif _, ok := reachable[n]; !ok {\n\t\t\treturn nil, nil, errors.Errorf(\"node %v in graph is unconnected\", n.id)\n\t\t}\n\t}\n\tfor n, e := range reachable {\n\t\tif _, ok := nodes[n]; !ok {\n\t\t\treturn nil, nil, errors.Errorf(\"node %v is reachable by edge %v, but it's not in same graph\", n.id, e.id)\n\t\t}\n\t}\n\treturn g.edges, g.nodes, nil\n}\n\nfunc (g *Graph) String() string {\n\tvar nodes []string\n\tfor _, node := range g.nodes {\n\t\tnodes = append(nodes, node.String())\n\t}\n\tvar edges []string\n\tfor _, edge := range g.edges {\n\t\tedges = append(edges, edge.String())\n\t}\n\treturn fmt.Sprintf(\"Nodes: %v\\nEdges: %v\", strings.Join(nodes, \"\\n\"), strings.Join(edges, \"\\n\"))\n}\n","sourceCodeStart":93,"sourceCodeEnd":128,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/go/pkg/beam/core/graph/graph.go#L93-L128","documentation":"Graph.Build() keeps a map of nodes reachable via edges and verifies each reachable node exists in the current graph's node set. When an edge points to a node that was created in (or attributed to) a different Graph, Build returns \"node %v is reachable by edge %v, but it's not in same graph\" — a graph-identity invariant violation.","triggerScenarios":"Building a Graph where an edge's Output.To (or Input.From) node was created by another Graph instance, e.g. mixing nodes across two g := graph.New() scopes or reusing nodes from a previous pipeline in a new one.","commonSituations":"Low-level custom transform code that creates nodes with one graph but edges with another; sharing PCollections/nodes between pipelines; copy-pasted graph-construction code using stale variables.","solutions":["Ensure every node referenced by an edge was created with the same Graph instance (same g.NewNode call chain).","Don't reuse PCollection/node values across pipeline or graph scopes; recreate them in the new graph.","Refactor custom transforms to receive the Graph from a single owner instead of constructing their own.","If hit via normal beam.Pipeline usage, this indicates an SDK bug — report with a minimal repro and pin/upgrade Beam version."],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use a single Graph instance for all node/edge creation in custom transforms.","Never reuse nodes/PCollections across pipeline or graph scopes."],"tags":["beam","go","graph","dag"],"backgroundTag":"internal-invariant-violation","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}