{"record":{"id":"76f0f2d003ba3cee","repo":"vitessio/vitess","slug":"failed-to-open-external-topo-v-76f0f2","errorCode":null,"errorMessage":"failed to open external topo: %v","messagePattern":"failed to open external topo: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/vt/wrangler/materializer.go","lineNumber":1109,"sourceCode":"\t}\n\tif len(ms.SourceShards) > 0 {\n\t\tvar targetShards2 []*topo.ShardInfo\n\t\tfor _, shard := range targetShards {\n\t\t\tif slices.Contains(ms.SourceShards, shard.ShardName()) {\n\t\t\t\ttargetShards2 = append(targetShards2, shard)\n\t\t\t}\n\t\t}\n\t\ttargetShards = targetShards2\n\t}\n\tif len(targetShards) == 0 {\n\t\treturn nil, fmt.Errorf(\"no target shards specified for workflow %s \", ms.Workflow)\n\t}\n\n\tsourceTs := wr.ts\n\tif ms.ExternalCluster != \"\" { // when the source is an external mysql cluster mounted using the Mount command\n\t\texternalTopo, err := wr.ts.OpenExternalVitessClusterServer(ctx, ms.ExternalCluster)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to open external topo: %v\", err)\n\t\t}\n\t\tsourceTs = externalTopo\n\t}\n\tdifferentPVs := false\n\tsourceVSchema, err := sourceTs.GetVSchema(ctx, ms.SourceKeyspace)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to get source keyspace vschema: %v\", err)\n\t}\n\tdifferentPVs = primaryVindexesDiffer(ms, sourceVSchema.Keyspace, vschema.Keyspace)\n\n\treturn &materializer{\n\t\twr:                    wr,\n\t\tms:                    ms,\n\t\ttargetVSchema:         targetVSchema,\n\t\tsourceShards:          sourceShards,\n\t\ttargetShards:          targetShards,\n\t\tisPartial:             isPartial,\n\t\tprimaryVindexesDiffer: differentPVs,","sourceCodeStart":1091,"sourceCodeEnd":1127,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/wrangler/materializer.go#L1091-L1127","documentation":"When the workflow sources from an external (mounted) Vitess cluster, buildMaterializer opens a topo server for that cluster via OpenExternalVitessClusterServer. Failure to open it is wrapped with this message.","triggerScenarios":"ms.ExternalCluster is set but the external cluster cannot be opened — bad mount config, unreachable topo servers, wrong topo flags, or credentials/connection problems to the external topo.","commonSituations":"Mount command saved incorrect topo server addresses; external cluster topo is down or network-firewalled; cluster was unmounted or renamed but the workflow still references the old name.","solutions":["Check the mount configuration (vtctldclient GetAllMounts / Show) and re-mount with correct topo server and root.","Verify network connectivity and topo server health for the external cluster.","Confirm the ExternalCluster name matches a currently mounted cluster; update the workflow if it was renamed."],"exampleFix":"// before: stale mount\n// workflow references cluster 'sale' that was unmounted\n// after\nvtctldclient Mount --topo-type etcd2 --topo-server srv1:2379 --name sale\n// then retry the MoveTables with --external-cluster sale","handlingStrategy":"validation","validationCode":"mounts, _ := vtctld.GetAllMounts(ctx)\nif !slices.ContainsFunc(mounts, func(m string) bool { return m == externalCluster }) {\n  return fmt.Errorf(\"external cluster %s not mounted\", externalCluster)\n}","typeGuard":null,"tryCatchPattern":"m, err := wr.ts.OpenExternalVitessClusterServer(ctx, cluster)\nif err != nil {\n  // log full error, verify mount config and topo connectivity, then re-mount\n}","preventionTips":["Verify mounts with GetAllMounts before workflows referencing an external cluster.","Monitor external topo server health and connectivity.","Update workflows after unmounting/renaming clusters."],"tags":["topology","external-cluster","network"],"backgroundTag":"external-topo-unreachable","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}