vitessio/vitess · error

both atomic copy and partial mode cannot be specified for th

Error message

both atomic copy and partial mode cannot be specified for the same workflow

What it means

getWorkflowSubType was asked to classify a workflow as both Partial and AtomicCopy simultaneously, which are mutually exclusive vreplication workflow sub-types. Wrangler rejects the combination because a workflow cannot atomically copy all tables and run in partial (subset) mode at the same time.

Source

Thrown at go/vt/wrangler/materializer.go:1460

func (mz *materializer) getWorkflowType() binlogdatapb.VReplicationWorkflowType {
	var workflowType binlogdatapb.VReplicationWorkflowType
	switch mz.ms.MaterializationIntent {
	case vtctldatapb.MaterializationIntent_CUSTOM:
		workflowType = binlogdatapb.VReplicationWorkflowType_Materialize
	case vtctldatapb.MaterializationIntent_MOVETABLES:
		workflowType = binlogdatapb.VReplicationWorkflowType_MoveTables
	case vtctldatapb.MaterializationIntent_CREATELOOKUPINDEX:
		workflowType = binlogdatapb.VReplicationWorkflowType_CreateLookupIndex
	}
	return workflowType
}

func (mz *materializer) getWorkflowSubType() (binlogdatapb.VReplicationWorkflowSubType, string, error) {
	workflowSubType := binlogdatapb.VReplicationWorkflowSubType_None
	switch {
	case mz.isPartial && mz.ms.AtomicCopy:
		return workflowSubType, "", errors.New("both atomic copy and partial mode cannot be specified for the same workflow")
	case mz.isPartial:
		workflowSubType = binlogdatapb.VReplicationWorkflowSubType_Partial
	case mz.ms.AtomicCopy:
		workflowSubType = binlogdatapb.VReplicationWorkflowSubType_AtomicCopy
	default:
		workflowSubType = binlogdatapb.VReplicationWorkflowSubType_None
	}
	return workflowSubType, "", nil
}

func matchColInSelect(col sqlparser.IdentifierCI, sel *sqlparser.Select) (*sqlparser.ColName, error) {
	for _, selExpr := range sel.GetColumns() {
		switch selExpr := selExpr.(type) {
		case *sqlparser.StarExpr:
			return &sqlparser.ColName{Name: col}, nil
		case *sqlparser.AliasedExpr:
			match := selExpr.As
			if match.IsEmpty() {

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Remove --atomic-copy if the workflow is intended to be partial
  2. Remove the partial-mode specification if a full atomic copy is intended
  3. Audit automation that composes MoveTables flags so only one sub-type is set

Example fix

// before
ms.AtomicCopy = true; mz.isPartial = true
// after: pick one
ms.AtomicCopy = true // OR mz.isPartial = true, not both
Defensive patterns

Strategy: validation

Validate before calling

// reject the combination before calling MoveTables
if opts.isPartial && opts.atomicCopy {
	return errors.New("pick either partial mode or atomic copy, not both")
}

Try / catch

subType, _, err := mz.getWorkflowSubType()
if err != nil && strings.Contains(err.Error(), "both atomic copy and partial") {
	// return a flag-usage error to the CLI caller
}

Prevention

When it happens

Trigger: Calling MoveTables (or another materializer-based workflow) with flags/inputs that set mz.isPartial while ms.AtomicCopy is true — e.g. combining --atomic-copy with a partial-tables/partition specification.

Common situations: CLI or API automation merging flag sets from two different workflows; users assuming atomic copy and partial copy are compatible; generated configs where both options default into the request.

Related errors


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