vitessio/vitess · error

migration %v cannot run because prior migration %v in same c

Error message

migration %v cannot run because prior migration %v in same context has failed/was cancelled

What it means

During schema analysis of a new online DDL migration, vttablet checks whether any prior migration submitted in the same context/keyspace has failed or been cancelled. If so, the new migration is immediately failed with this message to avoid building on an inconsistent schema change sequence.

Source

Thrown at go/vt/vttablet/onlineddl/executor.go:2451

	e.ownedRunningMigrations.Delete(onlineDDL.UUID)
	return withError
}

// validateInOrderMigration checks whether an in-order migration should be forced to fail, either before running or
// while running.
// This may happen if a prior migration in the same context has failed or was cancelled.
func (e *Executor) validateInOrderMigration(ctx context.Context, onlineDDL *schema.OnlineDDL) (wasFailed bool, err error) {
	if !onlineDDL.StrategySetting().IsInOrderCompletion() {
		return false, nil
	}
	uuids, err := e.readFailedCancelledMigrationsInContextBeforeMigration(ctx, onlineDDL)
	if err != nil {
		return false, err
	}
	if len(uuids) == 0 {
		return false, err
	}
	return true, e.failMigration(ctx, onlineDDL, fmt.Errorf("migration %v cannot run because prior migration %v in same context has failed/was cancelled", onlineDDL.UUID, uuids[0]))
}

// analyzeDropDDLActionMigration analyzes a DROP <TABLE|VIEW> migration.
func (e *Executor) analyzeDropDDLActionMigration(ctx context.Context, onlineDDL *schema.OnlineDDL) error {
	// Schema analysis:
	originalShowCreateTable, err := e.showCreateTable(ctx, onlineDDL.Table)
	if err != nil {
		if sqlErr, isSQLErr := sqlerror.NewSQLErrorFromError(err).(*sqlerror.SQLError); isSQLErr {
			switch sqlErr.Num {
			case sqlerror.ERNoSuchTable:
				// The table does not exist. For analysis purposed, that's fine.
				return nil
			default:
				return vterrors.Wrapf(err, "attempting to read definition of %v", onlineDDL.Table)
			}
		}
	}
	stmt, err := e.env.Environment().Parser().ParseStrictDDL(originalShowCreateTable)

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Find and fix the root cause of the earlier failed/cancelled migration (check its message via SHOW VITESS_MIGRATIONS)
  2. Retry or revert the failed migration so its status no longer blocks the context
  3. Submit the new migration in a different migration context if it is genuinely independent
  4. Cancel/clean up stale migrations in the queue before resubmitting
Defensive patterns

Strategy: validation

Validate before calling

// Before submitting a new migration, ensure no failed/cancelled migrations share the context
rows := query(t, "SELECT uuid FROM _vt.schema_migrations WHERE migration_context=? AND status IN ('failed','cancelled')", ctxName)
if len(rows) > 0 {
    return fmt.Errorf("context %s blocked by failed migration %s", ctxName, rows[0].uuid)
}

Try / catch

err := applySchema(ctx, ddl, migrationContext)
if err != nil && strings.Contains(err.Error(), "has failed/was cancelled") {
    // resolve the earlier failed migration, then resubmit
}

Prevention

When it happens

Trigger: Submitting an ALTER/DROP migration in the same migration context where an earlier migration (uuids[0]) ended in status 'failed' or 'cancelled'.

Common situations: A batch of sequential schema changes where migration #1 failed (e.g. table locked, timeout) and subsequent migrations in the same submit request are rejected; CI pipelines replaying migration sequences after a failure.

Related errors


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