{"record":{"id":"c213b22660f64f87","repo":"vitessio/vitess","slug":"found-no-possible-unique-key-on-s","errorCode":null,"errorMessage":"found no possible unique key on `%s`","messagePattern":"found no possible unique key on `(.+?)`","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/vt/schemadiff/onlineddl.go","lineNumber":550,"sourceCode":"\t\treturn columns.Filter(func(col *ColumnDefinitionEntity) bool {\n\t\t\treturn col.IsGenerated()\n\t\t})\n\t}\n\tnoDefaultColumns := func(columns *ColumnDefinitionEntityList) *ColumnDefinitionEntityList {\n\t\treturn columns.Filter(func(col *ColumnDefinitionEntity) bool {\n\t\t\treturn !col.HasDefault()\n\t\t})\n\t}\n\tsourceColumns := sourceCreateTableEntity.ColumnDefinitionEntitiesList()\n\ttargetColumns := targetCreateTableEntity.ColumnDefinitionEntitiesList()\n\n\tvar droppedSourceNonGeneratedColumns *ColumnDefinitionEntityList\n\tanalysis.SourceSharedColumns, analysis.TargetSharedColumns, droppedSourceNonGeneratedColumns, analysis.SharedColumnsMap = AnalyzeSharedColumns(sourceColumns, targetColumns, alterTableAnalysis)\n\n\t// unique keys\n\tsourceUniqueKeys := PrioritizedUniqueKeys(sourceCreateTableEntity)\n\tif sourceUniqueKeys.Len() == 0 {\n\t\treturn nil, fmt.Errorf(\"found no possible unique key on `%s`\", sourceCreateTableEntity.Name())\n\t}\n\n\ttargetUniqueKeys := PrioritizedUniqueKeys(targetCreateTableEntity)\n\tif targetUniqueKeys.Len() == 0 {\n\t\treturn nil, fmt.Errorf(\"found no possible unique key on `%s`\", targetCreateTableEntity.Name())\n\t}\n\t// VReplication supports completely different unique keys on source and target, covering\n\t// some/completely different columns. The condition is that the key on source\n\t// must use columns which all exist on target table.\n\teligibleSourceColumnsForUniqueKey := analysis.SourceSharedColumns.Union(generatedColumns(sourceColumns))\n\tanalysis.ChosenSourceUniqueKey = IterationKeysByColumns(sourceUniqueKeys, eligibleSourceColumnsForUniqueKey).First()\n\tif analysis.ChosenSourceUniqueKey == nil {\n\t\treturn nil, fmt.Errorf(\"found no possible unique key on `%s` whose columns are in target table `%s`\", sourceCreateTableEntity.Name(), targetCreateTableEntity.Name())\n\t}\n\n\teligibleTargetColumnsForUniqueKey := analysis.TargetSharedColumns.Union(generatedColumns(targetColumns))\n\tanalysis.ChosenTargetUniqueKey = IterationKeysByColumns(targetUniqueKeys, eligibleTargetColumnsForUniqueKey).First()\n\tif analysis.ChosenTargetUniqueKey == nil {","sourceCodeStart":532,"sourceCodeEnd":568,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/schemadiff/onlineddl.go#L532-L568","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Add a primary key or unique key to the table before running the online migration (a separate plain ALTER).","Ensure the ALTER statement itself doesn't drop the last unique key on the target definition.","Use a non-online DDL strategy (e.g. direct/standard MySQL ALTER) if keylessness is intentional and acceptable."],"exampleFix":"-- before (table has no unique key)\nALTER TABLE mytable MODIFY col INT;\n-- after: add a key first\nALTER TABLE mytable ADD COLUMN id BIGINT AUTO_INCREMENT PRIMARY KEY, MODIFY col INT;","handlingStrategy":"validation","validationCode":"func hasUsableUniqueKey(cte *schemadiff.CreateTableEntity) bool {\n    return cte != nil && schemadiff.PrioritizedUniqueKeys(cte).Len() > 0\n}","typeGuard":null,"tryCatchPattern":"analysis, err := schemadiff.OnlineDDLMigrationTablesAnalysis(...)\nif err != nil {\n    return fmt.Errorf(\"cannot run online DDL for this table: %w\", err)\n}","preventionTips":["Enforce primary/unique keys on all tables managed by online DDL (schema policy).","Review ALTERs that drop keys before submitting to online migration.","Fall back to a direct ALTER strategy for keyless legacy tables."],"tags":["online-schema-change","schemadiff","unique-key","ddl"],"backgroundTag":"missing-unique-key","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}