vitessio/vitess · error · ErrWorkflowDeleteWritesSwitched
cannot delete workflow because you have already switched wri
Error message
cannot delete workflow because you have already switched write traffic
What it means
WorkflowDelete (and TestWorkflowDelete) refuses to delete a MoveTables workflow after write traffic has already been switched to the target, because deleting it would drop the source tables' replication safety net / reverse replication. ErrWorkflowDeleteWritesSwitched is the sentinel for this guarded state.
Source
Thrown at go/vt/vtctl/workflow/server.go:128
lockTablesCycleDelay = time.Duration(100 * time.Millisecond)
SqlUnfreezeWorkflow = "update _vt.vreplication set state='Running', message='' where db_name=%a and workflow=%a"
)
var (
// ErrInvalidWorkflow is a catchall error type for conditions that should be
// impossible when operating on a workflow.
ErrInvalidWorkflow = errors.New("invalid workflow")
// ErrMultipleSourceKeyspaces occurs when a workflow somehow has multiple
// source keyspaces across different shard primaries. This should be
// impossible.
ErrMultipleSourceKeyspaces = errors.New("multiple source keyspaces for a single workflow")
// ErrMultipleTargetKeyspaces occurs when a workflow somehow has multiple
// target keyspaces across different shard primaries. This should be
// impossible.
ErrMultipleTargetKeyspaces = errors.New("multiple target keyspaces for a single workflow")
ErrWorkflowCompleteNotFullySwitched = errors.New("cannot complete workflow because you have not yet switched all read and write traffic")
ErrWorkflowDeleteWritesSwitched = errors.New("cannot delete workflow because you have already switched write traffic")
)
// Server provides an API to work with Vitess workflows, like vreplication
// workflows (MoveTables, Reshard, etc) and schema migration workflows.
type Server struct {
ts *topo.Server
tmc tmclient.TabletManagerClient
// Limit the number of concurrent background goroutines if needed.
sem *semaphore.Weighted
env *vtenv.Environment
options serverOptions
}
// NewServer returns a new server instance with the given topo.Server and
// TabletManagerClient.
func NewServer(env *vtenv.Environment, ts *topo.Server, tmc tmclient.TabletManagerClient, opts ...ServerOption) *Server {
s := &Server{
ts: ts,View on GitHub (pinned to 01a25a7d17)
Solutions
- Use `MoveTablesComplete` (or `WorkflowDelete` with the appropriate drop-source/table-removal options) instead of a plain delete after writes are switched.
- If you truly must remove the workflow, explicitly pass the drop-source / table removal type that documents the intent.
- Roll back write traffic (reverse SwitchWrites) first if the deletion was not intended.
Example fix
// before vtctldclient WorkflowDelete --workflow sales commerce // error: writes already switched // after vtctldclient MoveTablesComplete --workflow sales --drop_source commerce
Defensive patterns
Strategy: validation
Validate before calling
if writesSwitched(keyspace, workflow) {
return fmt.Errorf("use MoveTablesComplete --drop_source instead of delete for %s", workflow)
} Type guard
func isDeleteAfterWritesErr(err error) bool {
return errors.Is(err, workflow.ErrWorkflowDeleteWritesSwitched)
} Try / catch
if err := client.WorkflowDelete(ctx, ks, wf, false); err != nil {
if errors.Is(err, workflow.ErrWorkflowDeleteWritesSwitched) {
return client.MoveTablesComplete(ctx, ks, wf) // intended cleanup path
}
return err
} Prevention
- After switching writes, use MoveTablesComplete/DropSource for cleanup
- Do not use plain WorkflowDelete on finished MoveTables migrations
- Check traffic state before any delete operation
When it happens
Trigger: Calling WorkflowDelete on a workflow where SwitchWrites has completed (writes are now on the target keyspace) and the source tables would be removed or replication torn down unsafely.
Common situations: Operators cleaning up a finished MoveTables migration who call the plain delete command instead of `MoveTablesComplete`/DropSource with the intended table-removal behavior.
Related errors
- cannot complete workflow because you have not yet switched a
- both atomic copy and partial mode cannot be specified for th
- invalid workflow
- multiple source keyspaces for a single workflow
- multiple target keyspaces for a single workflow
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/6b81c555110cb0aa.
Report an issue: GitHub.