vitessio/vitess · error

failed to open external topo: %v

Error message

failed to open external topo: %v

What it means

When ms.ExternalCluster is set, the source lives on an externally mounted MySQL/Vitess cluster and buildMaterializer must open that cluster's topo server via OpenExternalVitessClusterServer. This error wraps any failure opening the external topo server, making the source topology unreachable.

Source

Thrown at go/vt/vtctl/workflow/materializer.go:553

	}
	if len(specifiedTargetShards) > 0 {
		var targetShards2 []*topo.ShardInfo
		for _, shard := range targetShards {
			if slices.Contains(specifiedTargetShards, shard.ShardName()) {
				targetShards2 = append(targetShards2, shard)
			}
		}
		targetShards = targetShards2
	}
	if len(targetShards) == 0 {
		return fmt.Errorf("no target shards specified for workflow %s ", ms.Workflow)
	}

	sourceTs := mz.ts
	if ms.ExternalCluster != "" { // when the source is an external mysql cluster mounted using the Mount command
		externalTopo, err := mz.ts.OpenExternalVitessClusterServer(ctx, ms.ExternalCluster)
		if err != nil {
			return fmt.Errorf("failed to open external topo: %v", err)
		}
		sourceTs = externalTopo
	}
	differentPVs := false
	sourceVSchema, err := sourceTs.GetVSchema(ctx, ms.SourceKeyspace)
	if err != nil {
		return fmt.Errorf("failed to get source keyspace vschema: %v", err)
	}
	differentPVs = primaryVindexesDiffer(ms, sourceVSchema.Keyspace, vschema.Keyspace)

	mz.targetVSchema = targetVSchema
	mz.sourceShards = sourceShards
	mz.targetShards = targetShards
	mz.isPartial = isPartial
	mz.primaryVindexesDiffer = differentPVs
	return nil
}

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Run `vtctl Mount` (or re-mount) the external cluster and confirm the name matches ms.ExternalCluster
  2. Verify connectivity to the external topo server (host, port, credentials)
  3. List mounts with `vtctl ListMounts` to confirm the cluster exists

Example fix

// before
MoveTables --external-cluster=prod_ext_x --source-keyspace=ks
// after
vtctl Mount --topo-type=etcd2 --topo-server=host:2379 ext0
MoveTables --external-cluster=ext0 --source-keyspace=ks
Defensive patterns

Strategy: validation

Validate before calling

mounts, err := ts.ListMounts(ctx)
if err != nil { return err }
if !containsMount(mounts, externalCluster) {
    return fmt.Errorf("mount %q not found; run Mount first", externalCluster)
}

Try / catch

if err := createWorkflow(ctx, req); err != nil {
    if strings.Contains(err.Error(), "failed to open external topo") {
        // check ListMounts, connectivity, and re-Mount the cluster
    }
    return err
}

Prevention

When it happens

Trigger: Workflow creation (createWorkflowStreams / WorkflowAddTables) with --external-cluster set while the external cluster name is wrong, the mount is stale, or the external topo server is unreachable.

Common situations: Cluster unmounted (or name typo) before workflow creation; network/firewall blocking the external topo; external topo credentials changed; stale mount after the external cluster was re-created.

Related errors


AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01). Data as JSON: /api/errors/edc70db50d06b637. Report an issue: GitHub.