vitessio/vitess · error
invalid format for external source cluster: %s
Error message
invalid format for external source cluster: %s
What it means
getSourceKeyspace parses an external cluster source string expected in the form 'externalClusterName.keyspaceName' (exactly one dot separator). This error is returned when the argument does not split into exactly two components, so the cluster name and source keyspace cannot be determined.
Source
Thrown at go/vt/vtctl/vtctl.go:2068
vReplicationWorkflowActionCreate = "create"
vReplicationWorkflowActionSwitchTraffic = "switchtraffic"
vReplicationWorkflowActionReverseTraffic = "reversetraffic"
vReplicationWorkflowActionComplete = "complete"
vReplicationWorkflowActionCancel = "cancel"
vReplicationWorkflowActionShow = "show"
vReplicationWorkflowActionProgress = "progress"
vReplicationWorkflowActionGetState = "getstate"
)
func commandMigrate(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error {
return commandVReplicationWorkflow(ctx, wr, subFlags, args, wrangler.MigrateWorkflow)
}
// getSourceKeyspace expects a keyspace of the form "externalClusterName.keyspaceName" and returns the components
func getSourceKeyspace(clusterKeyspace string) (clusterName string, sourceKeyspace string, err error) {
splits := strings.Split(clusterKeyspace, ".")
if len(splits) != 2 {
return "", "", fmt.Errorf("invalid format for external source cluster: %s", clusterKeyspace)
}
return splits[0], splits[1], nil
}
// commandVReplicationWorkflow is the common entry point for MoveTables/Reshard/Migrate workflows
// FIXME: this function needs a refactor. Also validations for params should to be done per workflow type
func commandVReplicationWorkflow(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string,
workflowType wrangler.VReplicationWorkflowType,
) error {
const defaultWaitTime = time.Duration(30 * time.Second)
// for backward compatibility we default the lag to match the timeout for switching primary traffic
// this should probably be much smaller so that target and source are almost in sync before switching traffic
const defaultMaxReplicationLagAllowed = defaultWaitTime
cells := subFlags.String("cells", "", "Cell(s) or CellAlias(es) (comma-separated) to replicate from.")
tabletTypesStr := subFlags.String("tablet_types", "in_order:REPLICA,PRIMARY", "Source tablet types to replicate from (e.g. PRIMARY, REPLICA, RDONLY). Note: SwitchTraffic overrides this default and uses in_order:RDONLY,REPLICA,PRIMARY to switch all traffic by default.")
dryRun := subFlags.Bool("dry_run", false, "Does a dry run of SwitchTraffic and only reports the actions to be taken. --dry_run is only supported for SwitchTraffic, ReverseTraffic and Complete.")
timeout := subFlags.Duration("timeout", defaultWaitTime, "Specifies the maximum time to wait, in seconds, for vreplication to catch up on primary migrations. The migration will be cancelled on a timeout. --timeout is only supported for SwitchTraffic and ReverseTraffic.")View on GitHub (pinned to 01a25a7d17)
Solutions
- Pass the value as `<externalClusterName>.<keyspaceName>` with exactly one dot
- Verify the external cluster name is registered in the topo (`ExternalCluster` config)
- Check the string for stray dots or extra components and fix them
- Confirm the flag you're using expects the external form (internal keyspaces don't need the prefix)
Example fix
// before vtctl MoveTables -source=commerce customer # missing cluster prefix // after vtctl MoveTables -source=ext1.commerce customer
Defensive patterns
Strategy: validation
Validate before calling
validate_external_source() {
local n=$(echo "$1" | awk -F. '{print NF-1}')
[[ "$n" -eq 1 ]] || { echo "expected <cluster>.<keyspace>, got: $1"; return 1; }
}
validate_external_source "$SOURCE" || exit 1 Try / catch
if err := runVtctl("MoveTables", "--source="+src, ...); err != nil {
if strings.Contains(err.Error(), "invalid format for external source cluster") {
// re-format as cluster.keyspace and retry
}
} Prevention
- Always prefix external-source keyspaces with the registered external cluster name
- Keep cluster.keyspace pairs in config, not ad-hoc strings
- Validate the single-dot format in wrapper scripts
- Distinguish internal workflows (no prefix) from external Migrate/MoveTables (prefix required)
When it happens
Trigger: Running commandVReplicationWorkflow-backed commands (MoveTables/Migrate with an external source) where the --source argument or keyspace param lacks the 'cluster.keyspace' format — e.g. zero dots ('commerce') or multiple dots ('c1.ks.extra').
Common situations: Forgetting to prefix the keyspace with the external cluster name during VReplication migrations; copying an internal keyspace name into a flag that requires the external form; typos adding a second dot.
Related errors
- found an entry from a previous run for migration id %d in _v
- failed to parse max_tps column: %v
- failed to parse max_replication_lag column: %v
- failed to parse pos column: %v
- failed to parse stop_pos column: %v
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/e0e913569ac5a848.
Report an issue: GitHub.