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

  1. Pass the value as `<externalClusterName>.<keyspaceName>` with exactly one dot
  2. Verify the external cluster name is registered in the topo (`ExternalCluster` config)
  3. Check the string for stray dots or extra components and fix them
  4. 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

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


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