{"record":{"id":"23fb6ad7c0a99433","repo":"vitessio/vitess","slug":"cannot-run-migration-s-reverting-s-found-d-art","errorCode":null,"errorMessage":"cannot run migration %s reverting %s: found %d artifact tables, expected maximum 1","messagePattern":"cannot run migration (.+?) reverting (.+?): found (.+?) artifact tables, expected maximum 1","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/vt/vttablet/onlineddl/executor.go","lineNumber":2214,"sourceCode":"\t\treturn err\n\t}\n\n\trevertedActionStr := row[\"ddl_action\"].ToString()\n\tswitch revertedActionStr {\n\tcase sqlparser.CreateStr:\n\t\t{\n\t\t\t// We are reverting a CREATE migration. The revert is to DROP, only we don't actually\n\t\t\t// drop the table, we rename it into lifecycle\n\t\t\t// Possibly this was a CREATE TABLE IF NOT EXISTS, and possibly the table already existed\n\t\t\t// before the DDL, in which case the CREATE was a noop. In that scenario we _do not_ drop\n\t\t\t// the table.\n\t\t\t// We can tell the difference by looking at the artifacts. A successful CREATE TABLE, where\n\t\t\t// a table actually gets created, has a sentry, dummy artifact. A noop has not.\n\n\t\t\tartifacts := row[\"artifacts\"].ToString()\n\t\t\tartifactTables := textutil.SplitDelimitedList(artifacts)\n\t\t\tif len(artifactTables) > 1 {\n\t\t\t\treturn fmt.Errorf(\"cannot run migration %s reverting %s: found %d artifact tables, expected maximum 1\", onlineDDL.UUID, revertMigration.UUID, len(artifactTables))\n\t\t\t}\n\t\t\tif len(artifactTables) == 0 {\n\t\t\t\t// This indicates no table was actually created. this must have been a CREATE TABLE IF NOT EXISTS where the table already existed.\n\t\t\t\t_ = e.onSchemaMigrationStatus(ctx, onlineDDL.UUID, schema.OnlineDDLStatusComplete, false, progressPctFull, etaSecondsNow, rowsCopiedUnknown, emptyHint)\n\t\t\t}\n\n\t\t\tfor _, artifactTable := range artifactTables {\n\t\t\t\tif err := e.updateArtifacts(ctx, onlineDDL.UUID, artifactTable); err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t\tonlineDDL.SQL = sqlparser.BuildParsedQuery(sqlRenameTable, revertMigration.Table, artifactTable).Query\n\t\t\t\tif _, err := e.executeDirectly(ctx, onlineDDL); err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\tcase sqlparser.DropStr:\n\t\t{","sourceCodeStart":2196,"sourceCodeEnd":2232,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/vttablet/onlineddl/executor.go#L2196-L2232","documentation":"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.","triggerScenarios":"Executing a REVERT of a CREATE TABLE migration whose 'artifacts' column in _vt.schema_migrations contains more than one delimited table name.","commonSituations":"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.","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"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Verify artifacts state before reverting a CREATE migration\nrow := queryRow(t, \"SELECT artifacts FROM _vt.schema_migrations WHERE uuid=?\", uuid)\nartifacts := splitDelimited(row.artifacts)\nif len(artifacts) > 1 {\n    return fmt.Errorf(\"migration %s has %d artifacts; clean up before revert\", uuid, len(artifacts))\n}","typeGuard":null,"tryCatchPattern":"err := submitRevert(ctx, uuid)\nif err != nil && strings.Contains(err.Error(), \"artifact tables, expected maximum 1\") {\n    // inspect and clean artifact tables manually, then retry\n}","preventionTips":["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"],"tags":["online-ddl","revert","create-table","artifacts"],"backgroundTag":"inconsistent-migration-artifacts","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}