vitessio/vitess · error
cannot run migration %s reverting %s: found %d artifact tabl
Error message
cannot run migration %s reverting %s: found %d artifact tables, expected maximum 1
What it means
When reverting a CREATE TABLE migration, vttablet inspects the artifacts (renamed/sentry tables) left behind by the original CREATE. A valid CREATE TABLE revert can have at most 1 artifact table (the sentry for a real create, none for a no-op). More than one artifact means the migration state is inconsistent and the revert is aborted.
Source
Thrown at go/vt/vttablet/onlineddl/executor.go:2214
return err
}
revertedActionStr := row["ddl_action"].ToString()
switch revertedActionStr {
case sqlparser.CreateStr:
{
// We are reverting a CREATE migration. The revert is to DROP, only we don't actually
// drop the table, we rename it into lifecycle
// Possibly this was a CREATE TABLE IF NOT EXISTS, and possibly the table already existed
// before the DDL, in which case the CREATE was a noop. In that scenario we _do not_ drop
// the table.
// We can tell the difference by looking at the artifacts. A successful CREATE TABLE, where
// a table actually gets created, has a sentry, dummy artifact. A noop has not.
artifacts := row["artifacts"].ToString()
artifactTables := textutil.SplitDelimitedList(artifacts)
if len(artifactTables) > 1 {
return fmt.Errorf("cannot run migration %s reverting %s: found %d artifact tables, expected maximum 1", onlineDDL.UUID, revertMigration.UUID, len(artifactTables))
}
if len(artifactTables) == 0 {
// This indicates no table was actually created. this must have been a CREATE TABLE IF NOT EXISTS where the table already existed.
_ = e.onSchemaMigrationStatus(ctx, onlineDDL.UUID, schema.OnlineDDLStatusComplete, false, progressPctFull, etaSecondsNow, rowsCopiedUnknown, emptyHint)
}
for _, artifactTable := range artifactTables {
if err := e.updateArtifacts(ctx, onlineDDL.UUID, artifactTable); err != nil {
return err
}
onlineDDL.SQL = sqlparser.BuildParsedQuery(sqlRenameTable, revertMigration.Table, artifactTable).Query
if _, err := e.executeDirectly(ctx, onlineDDL); err != nil {
return err
}
}
}
case sqlparser.DropStr:
{View on GitHub (pinned to 01a25a7d17)
Solutions
- Inspect the artifacts column for the original migration and remove stale/foreign artifact table entries (after verifying with SHOW TABLES)
- Drop leftover artifact tables manually and clear the artifacts field, then retry the revert
- Re-run the original migration instead of reverting if the state cannot be repaired
- Verify the revert targets the correct migration UUID
Defensive patterns
Strategy: validation
Validate before calling
// Verify artifacts state before reverting a CREATE migration
row := queryRow(t, "SELECT artifacts FROM _vt.schema_migrations WHERE uuid=?", uuid)
artifacts := splitDelimited(row.artifacts)
if len(artifacts) > 1 {
return fmt.Errorf("migration %s has %d artifacts; clean up before revert", uuid, len(artifacts))
} Try / catch
err := submitRevert(ctx, uuid)
if err != nil && strings.Contains(err.Error(), "artifact tables, expected maximum 1") {
// inspect and clean artifact tables manually, then retry
} Prevention
- Check leftover artifact tables (SHOW TABLES LIKE '%_%') before reverting
- Avoid concurrent reverts on the same migration
- Do not merge or edit artifacts fields manually
- Run reverts promptly after the original migration completes
When it happens
Trigger: Executing a REVERT of a CREATE TABLE migration whose 'artifacts' column in _vt.schema_migrations contains more than one delimited table name.
Common situations: Artifacts from a different migration were accidentally merged into the row, retry/replay of an old migration produced duplicate artifacts, or manual edits to the schema_migrations table.
Related errors
- cannot run a revert migration %v: %+v
- direct DDL is disabled
- online DDL is disabled
- Foreign key found
- RENAME clause found
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/23fb6ad7c0a99433.
Report an issue: GitHub.