vitessio/vitess · error

found no possible unique key on `%s` whose columns are in so

Error message

found no possible unique key on `%s` whose columns are in source table `%s`

What it means

Symmetric to the source-side check: the target table's unique keys are filtered to those whose columns all exist in the source table. If no target unique key qualifies, OnlineDDLMigrationTablesAnalysis fails, because VReplication must apply target-key-based operations against the source rows.

Source

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

	}

	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 {
		return nil, fmt.Errorf("found no possible unique key on `%s` whose columns are in source table `%s`", targetCreateTableEntity.Name(), sourceCreateTableEntity.Name())
	}

	analysis.AddedUniqueKeys = IntroducedUniqueConstraints(sourceUniqueKeys, targetUniqueKeys, alterTableAnalysis.ColumnRenameMap)
	analysis.RemovedUniqueKeys = RemovedUniqueConstraints(sourceUniqueKeys, targetUniqueKeys, alterTableAnalysis.ColumnRenameMap)
	analysis.RemovedForeignKeyNames, err = RemovedForeignKeyNames(sourceCreateTableEntity, targetCreateTableEntity)
	if err != nil {
		return nil, err
	}

	formalizeColumns := func(columnsLists ...*ColumnDefinitionEntityList) error {
		for _, colList := range columnsLists {
			for _, col := range colList.Entities {
				col.SetExplicitDefaultAndNull()
				if err := col.SetExplicitCharsetCollate(); err != nil {
					return err
				}
			}
		}

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Ensure the target's unique key columns exist on the source table
  2. Add the missing/renamed column to the source before migration, or keep the key on shared columns
  3. Provide the column rename mapping so the analyzer recognizes the shared column

Example fix

-- before (target unique key on new column 'tenant_id' absent on source)
ALTER TABLE t ADD UNIQUE KEY uk_tenant (tenant_id);
-- after: add column to source first, then migrate
ALTER TABLE t ADD COLUMN tenant_id BIGINT, ADD UNIQUE KEY uk_tenant (tenant_id);
Defensive patterns

Strategy: validation

Validate before calling

shared := analysis.TargetSharedColumns
for _, col := range chosenTargetUniqueKey.Columns { if !shared.Contains(col) { /* column missing on source */ } }

Prevention

When it happens

Trigger: Calling OnlineDDLMigrationTablesAnalysis when IterationKeysByColumns over the target unique keys against TargetSharedColumns ∪ generated target columns yields nil — e.g. the target's unique key covers a column added only on the target, or renamed without mapping.

Common situations: Target table gained a new column included in its PRIMARY/UNIQUE key while the source predates it; rename map missing the mapping so the column looks unshared; an Online DDL that altered a key to use a new column.

Related errors


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