vitessio/vitess · error

found no possible unique key on `%s`

Error message

found no possible unique key on `%s`

What it means

OnlineDDLMigrationTablesAnalysis (the schemadiff-based table-analysis step for online DDL) requires at least one usable unique key on both source and target tables to safely migrate rows. When PrioritizedUniqueKeys finds no primary key or unique index on the table, it aborts with this error naming the offending table.

Source

Thrown at go/vt/schemadiff/onlineddl.go:550

		return columns.Filter(func(col *ColumnDefinitionEntity) bool {
			return col.IsGenerated()
		})
	}
	noDefaultColumns := func(columns *ColumnDefinitionEntityList) *ColumnDefinitionEntityList {
		return columns.Filter(func(col *ColumnDefinitionEntity) bool {
			return !col.HasDefault()
		})
	}
	sourceColumns := sourceCreateTableEntity.ColumnDefinitionEntitiesList()
	targetColumns := targetCreateTableEntity.ColumnDefinitionEntitiesList()

	var droppedSourceNonGeneratedColumns *ColumnDefinitionEntityList
	analysis.SourceSharedColumns, analysis.TargetSharedColumns, droppedSourceNonGeneratedColumns, analysis.SharedColumnsMap = AnalyzeSharedColumns(sourceColumns, targetColumns, alterTableAnalysis)

	// unique keys
	sourceUniqueKeys := PrioritizedUniqueKeys(sourceCreateTableEntity)
	if sourceUniqueKeys.Len() == 0 {
		return nil, fmt.Errorf("found no possible unique key on `%s`", sourceCreateTableEntity.Name())
	}

	targetUniqueKeys := PrioritizedUniqueKeys(targetCreateTableEntity)
	if targetUniqueKeys.Len() == 0 {
		return nil, fmt.Errorf("found no possible unique key on `%s`", targetCreateTableEntity.Name())
	}
	// VReplication supports completely different unique keys on source and target, covering
	// some/completely different columns. The condition is that the key on source
	// must use columns which all exist on target table.
	eligibleSourceColumnsForUniqueKey := analysis.SourceSharedColumns.Union(generatedColumns(sourceColumns))
	analysis.ChosenSourceUniqueKey = IterationKeysByColumns(sourceUniqueKeys, eligibleSourceColumnsForUniqueKey).First()
	if analysis.ChosenSourceUniqueKey == nil {
		return nil, fmt.Errorf("found no possible unique key on `%s` whose columns are in target table `%s`", sourceCreateTableEntity.Name(), targetCreateTableEntity.Name())
	}

	eligibleTargetColumnsForUniqueKey := analysis.TargetSharedColumns.Union(generatedColumns(targetColumns))
	analysis.ChosenTargetUniqueKey = IterationKeysByColumns(targetUniqueKeys, eligibleTargetColumnsForUniqueKey).First()
	if analysis.ChosenTargetUniqueKey == nil {

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Add a primary key or unique key to the table before running the online migration (a separate plain ALTER).
  2. Ensure the ALTER statement itself doesn't drop the last unique key on the target definition.
  3. Use a non-online DDL strategy (e.g. direct/standard MySQL ALTER) if keylessness is intentional and acceptable.

Example fix

-- before (table has no unique key)
ALTER TABLE mytable MODIFY col INT;
-- after: add a key first
ALTER TABLE mytable ADD COLUMN id BIGINT AUTO_INCREMENT PRIMARY KEY, MODIFY col INT;
Defensive patterns

Strategy: validation

Validate before calling

func hasUsableUniqueKey(cte *schemadiff.CreateTableEntity) bool {
    return cte != nil && schemadiff.PrioritizedUniqueKeys(cte).Len() > 0
}

Try / catch

analysis, err := schemadiff.OnlineDDLMigrationTablesAnalysis(...)
if err != nil {
    return fmt.Errorf("cannot run online DDL for this table: %w", err)
}

Prevention

When it happens

Trigger: Calling OnlineDDLMigrationTablesAnalysis (directly or via analyzeTables) for an ALTER on a table that has neither a PRIMARY KEY nor any UNIQUE key, for either the source or the target (post-ALTER) definition.

Common situations: Legacy heap tables created without keys; tables where the migration's ALTER drops the only unique key/primary key on the target definition; partitioned or imported tables missing constraints.

Related errors


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