vitessio/vitess · error
too many vdiffs found (%d) for UUID %s keyspace %s and workf
Error message
too many vdiffs found (%d) for UUID %s keyspace %s and workflow %s on tablet %s
What it means
This error is thrown by the vdiff engine's show-action handler on a vttablet when a query for a vdiff record by UUID returns more than one row. The _vt.vdiff table should hold at most one row per (keyspace, workflow, UUID) triple, so multiple matches indicate corrupt or duplicated vdiff state. The handler aborts rather than guessing which record to summarize.
Source
Thrown at go/vt/vttablet/tabletmanager/vdiff/action.go:352
return err
}
if qr, err = dbClient.ExecuteFetch(query, 1); err != nil {
return err
}
switch len(qr.Rows) {
case 0:
return fmt.Errorf("no vdiff found for UUID %s keyspace %s and workflow %s on tablet %s",
vdiffUUID, req.Keyspace, req.Workflow, topoproto.TabletAliasString(vde.thisTablet.Alias))
case 1:
row := qr.Named().Row()
vdiffID, _ := row["id"].ToInt64()
summary, err := vde.getVDiffSummary(vdiffID, dbClient, req.GetOptions().GetReportOptions())
resp.Output = summary
if err != nil {
return err
}
default:
return fmt.Errorf("too many vdiffs found (%d) for UUID %s keyspace %s and workflow %s on tablet %s",
len(qr.Rows), vdiffUUID, req.Keyspace, req.Workflow, topoproto.TabletAliasString(vde.thisTablet.Alias))
}
}
switch req.ActionArg {
case AllActionArg:
query, err := sqlparser.ParseAndBind(sqlGetMostRecentVDiffByKeyspaceWorkflow,
sqltypes.StringBindVariable(req.Keyspace),
sqltypes.StringBindVariable(req.Workflow),
sqltypes.StringBindVariable(vde.dbName),
sqltypes.Int64BindVariable(maxVDiffsToReport),
)
if err != nil {
return err
}
if qr, err = dbClient.ExecuteFetch(query, -1); err != nil {
return err
}
resp.Output = sqltypes.ResultToProto3(qr)View on GitHub (pinned to 01a25a7d17)
Solutions
- Inspect the _vt.vdiff table on the tablet: SELECT * FROM _vt.vdiff WHERE vdiff_uuid='<uuid>' and identify the duplicate rows.
- Delete the stale/duplicate rows keeping the correct one (DELETE FROM _vt.vdiff WHERE id=<stale id>).
- Re-run the vdiff from scratch: delete all vdiff rows for the workflow and issue a fresh VDiff Create.
- If duplication came from a backup restore, pick a healthy tablet/shard and let vtctld vdiff operate against it.
Example fix
// before (mysql on tablet) SELECT id, vdiff_uuid, workflow FROM _vt.vdiff WHERE vdiff_uuid='6ba7b810-...'; -- returns 2 rows // after DELETE FROM _vt.vdiff WHERE id=42; -- keep the correct row -- then re-run: vtctldclient VDiff --keyspace ks --workflow wf show 6ba7b810-...
Defensive patterns
Strategy: validation
Validate before calling
rows, _ := tabletClient.Query("SELECT COUNT(*) FROM _vt.vdiff WHERE vdiff_uuid='"+uuid+"'")
if rows[0][0].AsInt64() > 1 { // dedupe before issuing show
cleanupDuplicates(uuid)
} Type guard
func hasSingleVDiffRow(n int) bool { return n == 1 } Prevention
- Never manually insert rows into _vt.vdiff without deleting existing ones for the same UUID.
- Check for duplicates with SELECT before issuing show against a recovered/restored tablet.
- Use vtctldclient vdiff delete all + create rather than surgical row edits.
- Verify tablet backups restore _vt.vdiff consistently.
When it happens
Trigger: Calling PerformVDiffAction with Action=Show and ActionArg set to a UUID when sqlGetVDiffID (or the UUID lookup query) matches len(qr.Rows) > 1 rows in the _vt.vdiff table on the tablet.
Common situations: Manual inserts into _vt.vdiff during debugging or recovery; orphaned/duplicated rows left by a crashed or interrupted vdiff; running the show against a tablet whose local _vt schema was restored from an inconsistent backup.
Related errors
- invalid state found for vdiff table %s (multiple records) fo
- checkpoint information not available in db for %v
- unable to perform time_zone conversions from %s to UTC — val
- unable to create vdiff for UUID %s on tablet %s (%w)
- no vdiff found for id %d on tablet %v
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/4765e639fd309b95.
Report an issue: GitHub.