vitessio/vitess · error

no tables in workflow %s.%s

Error message

no tables in workflow %s.%s

What it means

getWorkflowState builds the runtime state of a vreplication workflow (MoveTables/Migrate) and, for TABLES migration type, requires at least one table in the workflow since routing rules are derived from it. If ts.Tables() is empty, the workflow has no tables registered and state computation cannot proceed. Called from SwitchReads, SwitchWrites, and workflow construction.

Source

Thrown at go/vt/wrangler/traffic_switcher.go:267

	// spec, so we need to use the source of the reverse workflow, which is the
	// target of the workflow initiated by the user for checking routing rules.
	// Similarly we use a target shard of the reverse workflow as the original
	// source to check if writes have been switched.
	if strings.HasSuffix(workflowName, "_reverse") {
		reverse = true
		// Flip the source and target keyspaces.
		sourceKeyspace = state.TargetKeyspace
		targetKeyspace = state.SourceKeyspace
		workflowName = workflow.ReverseWorkflowName(workflowName)
	} else {
		sourceKeyspace = state.SourceKeyspace
	}
	if ts.MigrationType() == binlogdatapb.MigrationType_TABLES {
		state.WorkflowType = workflow.TypeMoveTables

		// We assume a consistent state, so only choose routing rule for one table.
		if len(ts.Tables()) == 0 {
			return nil, nil, fmt.Errorf("no tables in workflow %s.%s", targetKeyspace, workflowName)
		}
		table := ts.Tables()[0]

		if ts.isPartialMigration { // shard level traffic switching is all or nothing
			shardRoutingRules, err := wr.ts.GetShardRoutingRules(ctx)
			if err != nil {
				return nil, nil, err
			}

			rules := shardRoutingRules.Rules
			for _, rule := range rules {
				switch rule.ToKeyspace {
				case sourceKeyspace:
					state.ShardsNotYetSwitched = append(state.ShardsNotYetSwitched, rule.Shard)
				case targetKeyspace:
					state.ShardsAlreadySwitched = append(state.ShardsAlreadySwitched, rule.Shard)
				default:
					// Not a relevant rule.

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Verify the workflow name and keyspace: `vtctldclient VReplicationExec <tablet> 'show workflows'`
  2. If tables were removed unintentionally, recreate the MoveTables workflow with the intended table list
  3. If the workflow is leftover/complete, clean it up (MoveTables Complete / Delete workflow) instead of switching traffic
  4. Check the `_vt.vreplication` / workflow topology records to confirm which tables the workflow covers

Example fix

// before: switching traffic on a possibly empty workflow
state, _, err := wr.getWorkflowState(ctx, targetKeyspace, workflowName)
// after: guard before switching
if len(tables(workflowName)) == 0 {
	return fmt.Errorf("workflow %s.%s has no tables; check name or recreate", targetKeyspace, workflowName)
}
Defensive patterns

Strategy: validation

Validate before calling

wf, err := findWorkflow(ctx, targetKeyspace, workflowName)
if err != nil {
	return err
}
if len(wf.Tables) == 0 {
	return fmt.Errorf("workflow %s.%s has no tables; verify name or recreate", targetKeyspace, workflowName)
}

Type guard

func workflowHasTables(ts wrangler.TrafficSwitcher) bool {
	return ts.MigrationType() != binlogdatapb.MigrationType_TABLES || len(ts.Tables()) > 0
}

Try / catch

if _, _, err := wr.SwitchReads(ctx, targetKeyspace, workflowName, tables, direction); err != nil {
	if strings.Contains(err.Error(), "no tables in workflow") {
		// check `show workflows` and workflow name spelling
	}
	return err
}

Prevention

When it happens

Trigger: Calling MoveTables SwitchReads/SwitchWrites/CreateRoutingRules (or NewVReplicationWorkflow) for a workflow whose source tables list is empty — e.g. workflow created with no tables, all tables removed, or wrong workflow/keyspace name resolving to an empty table set.

Common situations: Typo in workflow name when running SwitchReads/SwitchWrites; MoveTables workflow whose tables were all dropped before traffic switch; partially-cleaned-up migration leaving an empty workflow entry; querying a keyspace that has a workflow record but no table registrations.

Related errors


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